From 14b0c5fdbf7645ede32913036996a903d8f9d815 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Fri, 19 May 2023 14:38:55 -0700 Subject: [PATCH 01/46] colton: ghidra runtime detection & GhidraFeatureExtractor --- capa/features/extractors/ghidra/__init__.py | 0 capa/features/extractors/ghidra/extractor.py | 14 +++++++ capa/features/extractors/ghidra/file.py | 0 capa/features/extractors/ghidra/global_.py | 0 capa/main.py | 39 ++++++++++++++++++++ 5 files changed, 53 insertions(+) create mode 100644 capa/features/extractors/ghidra/__init__.py create mode 100644 capa/features/extractors/ghidra/extractor.py create mode 100644 capa/features/extractors/ghidra/file.py create mode 100644 capa/features/extractors/ghidra/global_.py diff --git a/capa/features/extractors/ghidra/__init__.py b/capa/features/extractors/ghidra/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py new file mode 100644 index 000000000..65a5f13f9 --- /dev/null +++ b/capa/features/extractors/ghidra/extractor.py @@ -0,0 +1,14 @@ +import logging +import contextlib +from typing import Tuple, Iterator + +from capa.features.common import Feature +from capa.features.address import Address, AbsoluteVirtualAddress +from capa.features.extractors.base_extractor import FeatureExtractor +import capa.features.extractors.ghidra.global_ + +class GhidraFeatureExtractor(FeatureExtractor): + def __init__(self): + super().__init__() + self.global_features: List[Tuple[Feature, Address]] = [] + self.global_features.extend(capa.features.extractors.ghidra.global_.extract_os()) diff --git a/capa/features/extractors/ghidra/file.py b/capa/features/extractors/ghidra/file.py new file mode 100644 index 000000000..e69de29bb diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py new file mode 100644 index 000000000..e69de29bb diff --git a/capa/main.py b/capa/main.py index 14411b0eb..d56a04a1f 100644 --- a/capa/main.py +++ b/capa/main.py @@ -1311,6 +1311,31 @@ def ida_main(): print(capa.render.default.render(meta, rules, capabilities)) +def ghidra_main(): + import capa.rules + #import capa.render.default + #import capa.features.extractors.ghidra.extractor + import capa.features.extractors.ghidra.global_ + + logging.basicConfig(level=logging.INFO) + logging.getLogger().setLevel(logging.INFO) + + logger.debug("-" * 80) + logger.debug(" Using default embedded rules.") + logger.debug(" ") + logger.debug(" You can see the current default rule set here:") + logger.debug(" https://github.com/mandiant/capa-rules") + logger.debug("-" * 80) + + rules_path = os.path.join(get_default_root(), "rules") + logger.debug("rule path: %s", rules_path) + rules = get_rules([rules_path]) + + globl_features: List[Tuple[Feature, Address]] = [] + globl_features.extend(capa.features.extractors.ghidra.global_.extract_os()) + print(globl_features) + + def is_runtime_ida(): try: import idc @@ -1320,8 +1345,22 @@ def is_runtime_ida(): return True +def is_runtime_ghidra(): + try: + import ghidra.program.flatapi + except ImportError: + print("Not in Ghidra...") + return False + else: + return True + + if __name__ == "__main__": if is_runtime_ida(): ida_main() + elif is_runtime_ghidra(): + print("Calling Ghidra Main") + ghidra_main() else: sys.exit(main()) + From 1f09c923069be8597e21571d2836ce683578e3d8 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Fri, 19 May 2023 18:38:13 -0700 Subject: [PATCH 02/46] colton: OS extraction functionality implemented --- capa/features/extractors/ghidra/global_.py | 53 ++++++++++++++++++++++ capa/main.py | 2 - 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py index e69de29bb..645fd5877 100644 --- a/capa/features/extractors/ghidra/global_.py +++ b/capa/features/extractors/ghidra/global_.py @@ -0,0 +1,53 @@ +import logging +import contextlib +from io import BytesIO +from typing import Tuple, Iterator + +import ghidra.program.flatapi as flatapi +ghidraapi = flatapi.FlatProgramAPI(currentProgram) # Ghidrathon hacks :) + +import capa.features.extractors.elf +from capa.features.common import OS, ARCH_I386, ARCH_AMD64, OS_WINDOWS, Arch, Feature +from capa.features.address import NO_ADDRESS, Address + +logger = logging.getLogger(__name__) + +def extract_os() -> Iterator[Tuple[Feature, Address]]: + current_program = ghidraapi.getCurrentProgram() + format_name: str = current_program.getExecutableFormat() + + if "PE" in format_name: + yield OS(OS_WINDOWS), NO_ADDRESS + + elif "ELF" in format_name: + program_memory = current_program.getMemory() + fbytes_list = program_memory.getAllFileBytes() # java.util.List + fbytes = fbytes_list[0] # ghidra.program.database.mem.FileBytes + + # Java likes to return signed ints, so we must convert them + # back into unsigned bytes manually and write to BytesIO + pb_arr = b'' + for i in range(fbytes.getSize()): + pb_arr = pb_arr + (fbytes.getOriginalByte(i) & 0xff).to_bytes(1, 'little') + buf = BytesIO(pb_arr) + + with contextlib.closing(buf) as f: + os = capa.features.extractors.elf.detect_elf_os(f) + + yield OS(os), NO_ADDRESS + + else: + # we likely end up here: + # 1. handling shellcode, or + # 2. handling a new file format (e.g. macho) + # + # for (1) we can't do much - its shellcode and all bets are off. + # we could maybe accept a further CLI argument to specify the OS, + # but i think this would be rarely used. + # rules that rely on OS conditions will fail to match on shellcode. + # + # for (2), this logic will need to be updated as the format is implemented. + logger.debug("unsupported file format: %s, will not guess OS", format_name) + return + + diff --git a/capa/main.py b/capa/main.py index d56a04a1f..39a2632a0 100644 --- a/capa/main.py +++ b/capa/main.py @@ -1349,7 +1349,6 @@ def is_runtime_ghidra(): try: import ghidra.program.flatapi except ImportError: - print("Not in Ghidra...") return False else: return True @@ -1359,7 +1358,6 @@ def is_runtime_ghidra(): if is_runtime_ida(): ida_main() elif is_runtime_ghidra(): - print("Calling Ghidra Main") ghidra_main() else: sys.exit(main()) From ffe089d4448603d0ee67b6b9af5bf6fc82742e24 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Fri, 19 May 2023 19:10:39 -0700 Subject: [PATCH 03/46] colton: GhidraFeatureExtractor constructor pulls OS & Arch --- capa/features/extractors/ghidra/extractor.py | 1 + capa/features/extractors/ghidra/global_.py | 30 +++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py index 65a5f13f9..2f5a593ae 100644 --- a/capa/features/extractors/ghidra/extractor.py +++ b/capa/features/extractors/ghidra/extractor.py @@ -12,3 +12,4 @@ def __init__(self): super().__init__() self.global_features: List[Tuple[Feature, Address]] = [] self.global_features.extend(capa.features.extractors.ghidra.global_.extract_os()) + self.global_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py index 645fd5877..b0fad5cfc 100644 --- a/capa/features/extractors/ghidra/global_.py +++ b/capa/features/extractors/ghidra/global_.py @@ -3,6 +3,10 @@ from io import BytesIO from typing import Tuple, Iterator +# imports for clarity +# note: currentProgram is a static variable accessible in +# the specific ghidra runtime environment +import ghidra.program.database.mem import ghidra.program.flatapi as flatapi ghidraapi = flatapi.FlatProgramAPI(currentProgram) # Ghidrathon hacks :) @@ -20,12 +24,13 @@ def extract_os() -> Iterator[Tuple[Feature, Address]]: yield OS(OS_WINDOWS), NO_ADDRESS elif "ELF" in format_name: - program_memory = current_program.getMemory() + program_memory = current_program.getMemory() # ghidra.program.database.mem.MemoryMapDB fbytes_list = program_memory.getAllFileBytes() # java.util.List fbytes = fbytes_list[0] # ghidra.program.database.mem.FileBytes # Java likes to return signed ints, so we must convert them # back into unsigned bytes manually and write to BytesIO + # note: May be deprecated if Jep has implements better support for Java Lists pb_arr = b'' for i in range(fbytes.getSize()): pb_arr = pb_arr + (fbytes.getOriginalByte(i) & 0xff).to_bytes(1, 'little') @@ -51,3 +56,26 @@ def extract_os() -> Iterator[Tuple[Feature, Address]]: return +def extract_arch() -> Iterator[Tuple[Feature, Address]]: + current_program = ghidraapi.getCurrentProgram() + lang_id = current_program.getMetadata().get('Language ID') + + if 'x86' in lang_id and '64' in lang_id: + yield Arch(ARCH_AMD64), NO_ADDRESS + + elif 'x86' in lang_id and '32' in lang_id: + yield Arch(ARCH_I386), NO_ADDRESS + + elif 'x86' not in lang_id: + logger.debug("unsupported architecture: non-32-bit nor non-64-bit intel") + return + + else: + # we likely end up here: + # 1. handling a new architecture (e.g. aarch64) + # + # for (1), this logic will need to be updated as the format is implemented. + logger.debug("unsupported architecture: %s", lang_id) + return + + From 50afc2f9b204a330f1367e2bf2c6efdd7df901fa Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Fri, 26 May 2023 17:51:48 -0700 Subject: [PATCH 04/46] colton: developing ghidra backend tests --- capa/main.py | 1 + tests/test_ghidra_features.py | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/test_ghidra_features.py diff --git a/capa/main.py b/capa/main.py index 39a2632a0..6d270fc12 100644 --- a/capa/main.py +++ b/capa/main.py @@ -1333,6 +1333,7 @@ def ghidra_main(): globl_features: List[Tuple[Feature, Address]] = [] globl_features.extend(capa.features.extractors.ghidra.global_.extract_os()) + globl_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) print(globl_features) diff --git a/tests/test_ghidra_features.py b/tests/test_ghidra_features.py new file mode 100644 index 000000000..a4a9a748a --- /dev/null +++ b/tests/test_ghidra_features.py @@ -0,0 +1,25 @@ +import logging + +import fixtures +from fixtures import * + +import capa.main + +logger = logging.getLogger(__file__) + +# We need to skip the ghidra test if we cannot import ghidra modules, e.g., in GitHub CI. +ghidra_present: bool = False +try: + import ghidra.program.flatapi as flatapi + ghidraapi = flatapi.FlatProgramAPI(currentProgram) + + try: + current_program_test = ghidraapi.getCurrentProgram() + except RuntimeError as e: + logger.warning("Ghidra runtime not detected") + else: + ghidra_present = True +except ImportError: + pass + + From 78bd5e1e3b49796d5d58d33964dd6e22f02ba1b5 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Sun, 28 May 2023 19:04:31 -0700 Subject: [PATCH 05/46] colton: tests.yml installs Java, Ghidra, and Ghidrathon --- .github/workflows/tests.yml | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 64475f65a..27d82ab6d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -136,3 +136,43 @@ jobs: env: BN_LICENSE: ${{ secrets.BN_LICENSE }} run: pytest -v tests/test_binja_features.py # explicitly refer to the binja tests for performance. other tests run above. + + ghidra-tests: + name: Ghidra tests for ${{ matrix.python-version }} + runs-on: ubuntu-20.04 + needs: [code_style, rule_linter] + strategy: + fail-fast: false + matrix: + python-version: ["3.7", "3.11"] + java-version: ["17"] + steps: + - name: Checkout capa with submodules + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + with: + submodules: recursive + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # v4.5.0 + with: + python-version: ${{ matrix.python-version }} + - name: Set up Java ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: ${{ matrix.java-version }} + - name: Install Ghidra + run: | + mkdir ./.github/ghidra + wget "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_10.3_build/ghidra_10.3_PUBLIC_20230510.zip" -O ./.github/ghidra/ghidra_10.3_PUBLIC.zip + unzip .github/ghidra/ghidra_10.3_PUBLIC.zip -d .github/ghidra/ + env: + GHIDRA_INSTALL_DIR: /github/ghidra + - name: Install Ghidrathon + run : | + mkdir ./.github/ghidrathon + wget "" + - name: Install pyyaml + run: sudo apt-get install -y libyaml-dev + - name: Install capa + run: pip install -e .[dev] + From 8c40e82796a1da8fe678118964694060999bc58b Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Mon, 29 May 2023 19:58:59 -0700 Subject: [PATCH 06/46] configuring runner for ghidra tests --- .github/workflows/tests.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 27d82ab6d..de67a6f75 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -146,6 +146,7 @@ jobs: matrix: python-version: ["3.7", "3.11"] java-version: ["17"] + gradle-version: ["7.3"] steps: - name: Checkout capa with submodules uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 @@ -160,17 +161,31 @@ jobs: with: distribution: 'temurin' java-version: ${{ matrix.java-version }} - - name: Install Ghidra + - name: Set up Gradle ${{ matrix.gradle-version }} + uses: actions/gradle/gradle-build-action@v2 + with: + gradle-version: ${{ matrix.gradle-version }} + - name: Install Ghidra 10.3 run: | mkdir ./.github/ghidra wget "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_10.3_build/ghidra_10.3_PUBLIC_20230510.zip" -O ./.github/ghidra/ghidra_10.3_PUBLIC.zip unzip .github/ghidra/ghidra_10.3_PUBLIC.zip -d .github/ghidra/ + export PATH="/.github/ghidra/ghidra_10.3_PUBLIC/Support:$PATH" env: - GHIDRA_INSTALL_DIR: /github/ghidra + GHIDRA_INSTALL_DIR: /github/ghidra/ghidra_10.3_PUBLIC + GHIDRA_EXT_DIR: /github/ghidra/ghidra_10.3_PUBLIC/Extensions + - name: Install Jep 4.1.1 + run : | + mkdir ./.github/jep + wget "https://github.com/ninia/jep/archive/refs/tags/v4.1.1.zip" -O ./.github/jep/jep-4.1.1.zip + unzip .github/jep/jep-4.1.1.zip -d .github/jep/ + pip install .github/jep/jep-4.1.1/ - name: Install Ghidrathon run : | mkdir ./.github/ghidrathon - wget "" + wget "https://github.com/mandiant/Ghidrathon/archive/refs/tags/v2.1.0.zip" -O ./.github/ghidrathon/ghidrathon-2.1.0.zip + unzip .github/ghidrathon/ghidrathon-2.1.0.zip -d .github/ghidrathon/ + gradle -p ./.github/ghidrathon/Ghidrathon-2.1.0/ - name: Install pyyaml run: sudo apt-get install -y libyaml-dev - name: Install capa From b35cfdaf6ae339cef35b3f2a871c05abbd9bc0b1 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Mon, 29 May 2023 20:13:35 -0700 Subject: [PATCH 07/46] workflow_dispatch - temp --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index de67a6f75..fb8cc232c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -5,6 +5,7 @@ on: branches: [ master ] pull_request: branches: [ master ] + workflow_dispatch: # save workspaces to speed up testing env: From 73183e9c1970831d2b479ed40a13d8085019709d Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Mon, 29 May 2023 20:16:10 -0700 Subject: [PATCH 08/46] run tests.yml on workflow dispatch --- .github/workflows/tests.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fb8cc232c..4ab33047d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,11 +1,6 @@ name: CI -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - workflow_dispatch: +on: workflow_dispatch # save workspaces to speed up testing env: From 5af1a42bf1e0c45b2b303436423a9a007e537e77 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Mon, 29 May 2023 20:24:37 -0700 Subject: [PATCH 09/46] reverting tests.yml --- .github/workflows/tests.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4ab33047d..f346e5a3b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,6 +1,10 @@ name: CI -on: workflow_dispatch +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] # save workspaces to speed up testing env: From 16444fe5edececfebc9be31cefb039462a1bd952 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Thu, 1 Jun 2023 11:24:21 -0700 Subject: [PATCH 10/46] first working CI install --- .github/workflows/tests.yml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f346e5a3b..f4933e5f6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -140,13 +140,11 @@ jobs: ghidra-tests: name: Ghidra tests for ${{ matrix.python-version }} runs-on: ubuntu-20.04 - needs: [code_style, rule_linter] strategy: fail-fast: false matrix: python-version: ["3.7", "3.11"] java-version: ["17"] - gradle-version: ["7.3"] steps: - name: Checkout capa with submodules uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 @@ -161,19 +159,16 @@ jobs: with: distribution: 'temurin' java-version: ${{ matrix.java-version }} - - name: Set up Gradle ${{ matrix.gradle-version }} - uses: actions/gradle/gradle-build-action@v2 - with: - gradle-version: ${{ matrix.gradle-version }} + - name: Set up Gradle 7.3 # must be done manually due to no gradle build in capa + run: | + mkdir /opt/gradle + wget "https://services.gradle.org/distributions/gradle-7.3-bin.zip" -O /opt/gradle/gradle-7.3.zip + unzip /opt/gradle/gradle-7.3.zip -d /opt/gradle - name: Install Ghidra 10.3 run: | mkdir ./.github/ghidra wget "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_10.3_build/ghidra_10.3_PUBLIC_20230510.zip" -O ./.github/ghidra/ghidra_10.3_PUBLIC.zip unzip .github/ghidra/ghidra_10.3_PUBLIC.zip -d .github/ghidra/ - export PATH="/.github/ghidra/ghidra_10.3_PUBLIC/Support:$PATH" - env: - GHIDRA_INSTALL_DIR: /github/ghidra/ghidra_10.3_PUBLIC - GHIDRA_EXT_DIR: /github/ghidra/ghidra_10.3_PUBLIC/Extensions - name: Install Jep 4.1.1 run : | mkdir ./.github/jep @@ -185,7 +180,9 @@ jobs: mkdir ./.github/ghidrathon wget "https://github.com/mandiant/Ghidrathon/archive/refs/tags/v2.1.0.zip" -O ./.github/ghidrathon/ghidrathon-2.1.0.zip unzip .github/ghidrathon/ghidrathon-2.1.0.zip -d .github/ghidrathon/ - gradle -p ./.github/ghidrathon/Ghidrathon-2.1.0/ + workdir=$(pwd) + /opt/gradle/gradle-7.3/bin/gradle -p ./.github/ghidrathon/Ghidrathon-2.1.0/ -PGHIDRA_INSTALL_DIR=$workdir/.github/ghidra/ghidra_10.3_PUBLIC + unzip .github/ghidrathon/Ghidrathon-2.1.0/dist/*.zip -d $workdir/.github/ghidra/ghidra_10.3_PUBLIC/Extensions - name: Install pyyaml run: sudo apt-get install -y libyaml-dev - name: Install capa From b849cfd4a5b0ebf302951b61570ccdb68e6d459a Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Fri, 2 Jun 2023 22:41:29 -0700 Subject: [PATCH 11/46] ghidra ci setup, test files in development --- .github/workflows/tests.yml | 2 +- tests/fixtures.py | 12 +++++++++++ tests/test_ghidra_features.py | 38 +++++++++++++++++++++++++++++++---- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f4933e5f6..841044ee1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -155,7 +155,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Set up Java ${{ matrix.java-version }} - uses: actions/setup-java@v3 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3 with: distribution: 'temurin' java-version: ${{ matrix.java-version }} diff --git a/tests/fixtures.py b/tests/fixtures.py index 04c9c53bb..612f49a77 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -183,6 +183,18 @@ def get_binja_extractor(path): return extractor +@lru_cache(maxsize=1) +def get_ghidra_extractor(path): + import capa.features.extractors.ghidra.extractor + + extractor = capa.features.extractors.ghidra.extractor.GhidraFeatureExtractor(path) + + # overload the extractor so that the fixture exposes `extractor.path` + setattr(extractor, "path", path) + + return extractor + + def extract_global_features(extractor): features = collections.defaultdict(set) for feature, va in extractor.extract_global_features(): diff --git a/tests/test_ghidra_features.py b/tests/test_ghidra_features.py index a4a9a748a..ff8e6485a 100644 --- a/tests/test_ghidra_features.py +++ b/tests/test_ghidra_features.py @@ -1,11 +1,21 @@ +import sys import logging +import os.path +import binascii +import traceback -import fixtures -from fixtures import * +import pytest + +try: + sys.path.append(os.path.dirname(__file__)) + import fixtures + from fixtures import * +finally: + sys.path.pop() -import capa.main -logger = logging.getLogger(__file__) +logger = logging.getLogger("test_ghidra_features") + # We need to skip the ghidra test if we cannot import ghidra modules, e.g., in GitHub CI. ghidra_present: bool = False @@ -23,3 +33,23 @@ pass +@pytest.mark.skipif(ghidra_present is False, reason="Skip ghidra tests if the ghidra Python API is not installed") +@fixtures.parametrize( + "sample,scope,feature,expected", + fixtures.FEATURE_PRESENCE_TESTS, + indirect=["sample", "scope"], +) +def test_ghidra_features(sample, scope, feature, expected): + fixtures.do_test_feature_presence(fixtures.get_ghidra_extractor, sample, scope, feature, expected) + + +@pytest.mark.skipif(ghidra_present is False, reason="Skip ghidra tests if the ghidra Python API is not installed") +@fixtures.parametrize( + "sample,scope,feature,expected", + fixtures.FEATURE_COUNT_TESTS, + indirect=["sample", "scope"], +) +def test_ghidra_feature_counts(sample, scope, feature, expected): + fixtures.do_test_feature_count(fixtures.get_ghidra_extractor, sample, scope, feature, expected) + + From a7639d33b910457a9fe98cbf63bad2e48b15cb99 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Fri, 2 Jun 2023 23:11:18 -0700 Subject: [PATCH 12/46] colton: update CHANGELOG --- CHANGELOG.md | 3 ++- capa/main.py | 1 + rules | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fe6ae2b2..27915d5ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### New Features - Utility script to detect feature overlap between new and existing CAPA rules [#1451](https://github.com/mandiant/capa/issues/1451) [@Aayush-Goel-04](https://github.com/aayush-goel-04) +- extractor: Implement Ghidra Backend [@colton-gabertan](https://github.com/colton-gabertan) ### Breaking Changes @@ -16,7 +17,7 @@ - communication/mailslot/read-from-mailslot nick.simonian@mandiant.com - nursery/hash-data-using-sha512managed-in-dotnet jonathanlepore@google.com - nursery/compiled-with-exescript jonathanlepore@google.com -- + ### Bug Fixes - extractor: update vivisect Arch extraction #1334 @mr-tz diff --git a/capa/main.py b/capa/main.py index ee9676cd6..d4978d31a 100644 --- a/capa/main.py +++ b/capa/main.py @@ -1337,6 +1337,7 @@ def ghidra_main(): logger.debug("rule path: %s", rules_path) rules = get_rules([rules_path]) + # temp test for OS & ARCH extractions globl_features: List[Tuple[Feature, Address]] = [] globl_features.extend(capa.features.extractors.ghidra.global_.extract_os()) globl_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) diff --git a/rules b/rules index 188e65528..312d4cad8 160000 --- a/rules +++ b/rules @@ -1 +1 @@ -Subproject commit 188e65528ec496eaaa792c3470cb4ab680a1b156 +Subproject commit 312d4cad891498e1d360dffcc98f669b63869c94 From 3da233dcad430d2af14b40e7651d997690a7336d Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Wed, 7 Jun 2023 13:04:49 -0700 Subject: [PATCH 13/46] colton: removed redundant imports & object, locally tested --- capa/features/extractors/ghidra/global_.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py index b0fad5cfc..2409bf0cd 100644 --- a/capa/features/extractors/ghidra/global_.py +++ b/capa/features/extractors/ghidra/global_.py @@ -3,13 +3,6 @@ from io import BytesIO from typing import Tuple, Iterator -# imports for clarity -# note: currentProgram is a static variable accessible in -# the specific ghidra runtime environment -import ghidra.program.database.mem -import ghidra.program.flatapi as flatapi -ghidraapi = flatapi.FlatProgramAPI(currentProgram) # Ghidrathon hacks :) - import capa.features.extractors.elf from capa.features.common import OS, ARCH_I386, ARCH_AMD64, OS_WINDOWS, Arch, Feature from capa.features.address import NO_ADDRESS, Address @@ -17,14 +10,13 @@ logger = logging.getLogger(__name__) def extract_os() -> Iterator[Tuple[Feature, Address]]: - current_program = ghidraapi.getCurrentProgram() - format_name: str = current_program.getExecutableFormat() + format_name: str = currentProgram.getExecutableFormat() if "PE" in format_name: yield OS(OS_WINDOWS), NO_ADDRESS elif "ELF" in format_name: - program_memory = current_program.getMemory() # ghidra.program.database.mem.MemoryMapDB + program_memory = currentProgram.getMemory() # ghidra.program.database.mem.MemoryMapDB fbytes_list = program_memory.getAllFileBytes() # java.util.List fbytes = fbytes_list[0] # ghidra.program.database.mem.FileBytes @@ -57,8 +49,7 @@ def extract_os() -> Iterator[Tuple[Feature, Address]]: def extract_arch() -> Iterator[Tuple[Feature, Address]]: - current_program = ghidraapi.getCurrentProgram() - lang_id = current_program.getMetadata().get('Language ID') + lang_id = currentProgram.getMetadata().get('Language ID') if 'x86' in lang_id and '64' in lang_id: yield Arch(ARCH_AMD64), NO_ADDRESS From 855463b3195aa74edfab110a5b8299f09f082c48 Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Wed, 5 Jul 2023 17:48:45 -0700 Subject: [PATCH 14/46] Add Ghidra Backend CI configuration, fix CHANGELOG (#1529) * ghidra-backend ci working, fix CHANGELOG * temp: Add backend-ghidra to CI test workflow & add versioning to matrix * lint to avoid failure * linting for CI * cleanup CI, integrate actions, simplify installations * fix gradle repo * fix typo * fix submodule checkout for rules & test data * fix relative test data path * remove unnecessary steps * add flag to mkdir to resolve pipeline failure --- .github/mypy/mypy.ini | 3 ++ .github/workflows/tests.yml | 51 ++++++++++-------- CHANGELOG.md | 2 +- capa/features/extractors/ghidra/extractor.py | 5 +- capa/features/extractors/ghidra/global_.py | 28 +++++----- capa/main.py | 9 ++-- tests/fixtures.py | 12 ----- tests/test_ghidra_features.py | 55 -------------------- 8 files changed, 56 insertions(+), 109 deletions(-) delete mode 100644 tests/test_ghidra_features.py diff --git a/.github/mypy/mypy.ini b/.github/mypy/mypy.ini index c80af3de2..505d5772c 100644 --- a/.github/mypy/mypy.ini +++ b/.github/mypy/mypy.ini @@ -83,3 +83,6 @@ ignore_missing_imports = True [mypy-netnode.*] ignore_missing_imports = True + +[mypy-ghidra.*] +ignore_missing_imports = True diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 841044ee1..39cda1a39 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ master ] + branches: [ master, backend-ghidra ] pull_request: - branches: [ master ] + branches: [ master, backend-ghidra ] # save workspaces to speed up testing env: @@ -140,16 +140,22 @@ jobs: ghidra-tests: name: Ghidra tests for ${{ matrix.python-version }} runs-on: ubuntu-20.04 + needs: [code_style, rule_linter] strategy: fail-fast: false matrix: python-version: ["3.7", "3.11"] java-version: ["17"] + gradle-version: ["7.3"] + ghidra-version: ["10.3"] + public-version: ["PUBLIC_20230510"] # for ghidra releases + jep-version: ["4.1.1"] + ghidrathon-version: ["2.1.0"] steps: - name: Checkout capa with submodules uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 with: - submodules: recursive + submodules: true - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # v4.5.0 with: @@ -159,32 +165,33 @@ jobs: with: distribution: 'temurin' java-version: ${{ matrix.java-version }} - - name: Set up Gradle 7.3 # must be done manually due to no gradle build in capa - run: | - mkdir /opt/gradle - wget "https://services.gradle.org/distributions/gradle-7.3-bin.zip" -O /opt/gradle/gradle-7.3.zip - unzip /opt/gradle/gradle-7.3.zip -d /opt/gradle - - name: Install Ghidra 10.3 + - name: Set up Gradle ${{ matrix.gradle-version }} + uses: gradle/gradle-build-action@40b6781dcdec2762ad36556682ac74e31030cfe2 # v2.5.1 + with: + gradle-version: ${{ matrix.gradle-version }} + - name: Install Jep ${{ matrix.jep-version }} + run : pip install jep==${{ matrix.jep-version }} + - name: Install Ghidra ${{ matrix.ghidra-version }} run: | mkdir ./.github/ghidra - wget "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_10.3_build/ghidra_10.3_PUBLIC_20230510.zip" -O ./.github/ghidra/ghidra_10.3_PUBLIC.zip - unzip .github/ghidra/ghidra_10.3_PUBLIC.zip -d .github/ghidra/ - - name: Install Jep 4.1.1 - run : | - mkdir ./.github/jep - wget "https://github.com/ninia/jep/archive/refs/tags/v4.1.1.zip" -O ./.github/jep/jep-4.1.1.zip - unzip .github/jep/jep-4.1.1.zip -d .github/jep/ - pip install .github/jep/jep-4.1.1/ + mkdir ./.github/ghidra/project + wget "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_${{ matrix.ghidra-version }}_build/ghidra_${{ matrix.ghidra-version }}_${{ matrix.public-version }}.zip" -O ./.github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC.zip + unzip .github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC.zip -d .github/ghidra/ - name: Install Ghidrathon run : | mkdir ./.github/ghidrathon - wget "https://github.com/mandiant/Ghidrathon/archive/refs/tags/v2.1.0.zip" -O ./.github/ghidrathon/ghidrathon-2.1.0.zip - unzip .github/ghidrathon/ghidrathon-2.1.0.zip -d .github/ghidrathon/ + mkdir -p ~/.ghidra/.ghidra_${{ matrix.ghidra-version }}_PUBLIC/Extensions + wget "https://github.com/mandiant/Ghidrathon/archive/refs/tags/v${{ matrix.ghidrathon-version }}.zip" -O ./.github/ghidrathon/ghidrathon-${{ matrix.ghidrathon-version }}.zip + unzip .github/ghidrathon/ghidrathon-${{ matrix.ghidrathon-version }}.zip -d .github/ghidrathon/ workdir=$(pwd) - /opt/gradle/gradle-7.3/bin/gradle -p ./.github/ghidrathon/Ghidrathon-2.1.0/ -PGHIDRA_INSTALL_DIR=$workdir/.github/ghidra/ghidra_10.3_PUBLIC - unzip .github/ghidrathon/Ghidrathon-2.1.0/dist/*.zip -d $workdir/.github/ghidra/ghidra_10.3_PUBLIC/Extensions + gradle -p ./.github/ghidrathon/Ghidrathon-${{ matrix.ghidrathon-version }}/ -PGHIDRA_INSTALL_DIR=$workdir/.github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC + unzip .github/ghidrathon/Ghidrathon-${{ matrix.ghidrathon-version }}/dist/*.zip -d ~/.ghidra/.ghidra_${{ matrix.ghidra-version }}_PUBLIC/Extensions - name: Install pyyaml run: sudo apt-get install -y libyaml-dev - name: Install capa - run: pip install -e .[dev] + run: pip install -e .[dev] + - name: Run tests + run: | # runs main.py for now... + .github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC/support/analyzeHeadless .github/ghidra/project ghidra_test -Import ./tests/data/'Practical Malware Analysis Lab 01-01.dll_' + .github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC/support/analyzeHeadless .github/ghidra/project ghidra_test -process 'Practical Malware Analysis Lab 01-01.dll_' -ScriptPath ./capa -PostScript main.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 27915d5ef..ec03dad34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,6 @@ ### New Features - Utility script to detect feature overlap between new and existing CAPA rules [#1451](https://github.com/mandiant/capa/issues/1451) [@Aayush-Goel-04](https://github.com/aayush-goel-04) -- extractor: Implement Ghidra Backend [@colton-gabertan](https://github.com/colton-gabertan) ### Breaking Changes @@ -17,6 +16,7 @@ - communication/mailslot/read-from-mailslot nick.simonian@mandiant.com - nursery/hash-data-using-sha512managed-in-dotnet jonathanlepore@google.com - nursery/compiled-with-exescript jonathanlepore@google.com +- ### Bug Fixes diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py index 2f5a593ae..65b067064 100644 --- a/capa/features/extractors/ghidra/extractor.py +++ b/capa/features/extractors/ghidra/extractor.py @@ -1,11 +1,12 @@ import logging import contextlib -from typing import Tuple, Iterator +from typing import List, Tuple, Iterator +import capa.features.extractors.ghidra.global_ from capa.features.common import Feature from capa.features.address import Address, AbsoluteVirtualAddress from capa.features.extractors.base_extractor import FeatureExtractor -import capa.features.extractors.ghidra.global_ + class GhidraFeatureExtractor(FeatureExtractor): def __init__(self): diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py index 2409bf0cd..33a1237c2 100644 --- a/capa/features/extractors/ghidra/global_.py +++ b/capa/features/extractors/ghidra/global_.py @@ -1,13 +1,17 @@ import logging import contextlib from io import BytesIO -from typing import Tuple, Iterator +from typing import Tuple, Iterator + +import ghidra import capa.features.extractors.elf from capa.features.common import OS, ARCH_I386, ARCH_AMD64, OS_WINDOWS, Arch, Feature from capa.features.address import NO_ADDRESS, Address logger = logging.getLogger(__name__) +currentProgram: ghidra.program.database.ProgramDB + def extract_os() -> Iterator[Tuple[Feature, Address]]: format_name: str = currentProgram.getExecutableFormat() @@ -16,16 +20,16 @@ def extract_os() -> Iterator[Tuple[Feature, Address]]: yield OS(OS_WINDOWS), NO_ADDRESS elif "ELF" in format_name: - program_memory = currentProgram.getMemory() # ghidra.program.database.mem.MemoryMapDB - fbytes_list = program_memory.getAllFileBytes() # java.util.List - fbytes = fbytes_list[0] # ghidra.program.database.mem.FileBytes + program_memory = currentProgram.getMemory() # ghidra.program.database.mem.MemoryMapDB + fbytes_list = program_memory.getAllFileBytes() # java.util.List + fbytes = fbytes_list[0] # ghidra.program.database.mem.FileBytes # Java likes to return signed ints, so we must convert them # back into unsigned bytes manually and write to BytesIO - # note: May be deprecated if Jep has implements better support for Java Lists - pb_arr = b'' + # note: May be deprecated if Jep has implements better support for Java Lists + pb_arr = b"" for i in range(fbytes.getSize()): - pb_arr = pb_arr + (fbytes.getOriginalByte(i) & 0xff).to_bytes(1, 'little') + pb_arr = pb_arr + (fbytes.getOriginalByte(i) & 0xFF).to_bytes(1, "little") buf = BytesIO(pb_arr) with contextlib.closing(buf) as f: @@ -49,15 +53,15 @@ def extract_os() -> Iterator[Tuple[Feature, Address]]: def extract_arch() -> Iterator[Tuple[Feature, Address]]: - lang_id = currentProgram.getMetadata().get('Language ID') + lang_id = currentProgram.getMetadata().get("Language ID") - if 'x86' in lang_id and '64' in lang_id: + if "x86" in lang_id and "64" in lang_id: yield Arch(ARCH_AMD64), NO_ADDRESS - elif 'x86' in lang_id and '32' in lang_id: + elif "x86" in lang_id and "32" in lang_id: yield Arch(ARCH_I386), NO_ADDRESS - elif 'x86' not in lang_id: + elif "x86" not in lang_id: logger.debug("unsupported architecture: non-32-bit nor non-64-bit intel") return @@ -68,5 +72,3 @@ def extract_arch() -> Iterator[Tuple[Feature, Address]]: # for (1), this logic will need to be updated as the format is implemented. logger.debug("unsupported architecture: %s", lang_id) return - - diff --git a/capa/main.py b/capa/main.py index d4978d31a..8326759ec 100644 --- a/capa/main.py +++ b/capa/main.py @@ -1319,9 +1319,11 @@ def ida_main(): def ghidra_main(): import capa.rules - #import capa.render.default - #import capa.features.extractors.ghidra.extractor + + # import capa.render.default + # import capa.features.extractors.ghidra.extractor import capa.features.extractors.ghidra.global_ + from capa.features.common import Feature logging.basicConfig(level=logging.INFO) logging.getLogger().setLevel(logging.INFO) @@ -1336,7 +1338,7 @@ def ghidra_main(): rules_path = os.path.join(get_default_root(), "rules") logger.debug("rule path: %s", rules_path) rules = get_rules([rules_path]) - + # temp test for OS & ARCH extractions globl_features: List[Tuple[Feature, Address]] = [] globl_features.extend(capa.features.extractors.ghidra.global_.extract_os()) @@ -1369,4 +1371,3 @@ def is_runtime_ghidra(): ghidra_main() else: sys.exit(main()) - diff --git a/tests/fixtures.py b/tests/fixtures.py index 612f49a77..04c9c53bb 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -183,18 +183,6 @@ def get_binja_extractor(path): return extractor -@lru_cache(maxsize=1) -def get_ghidra_extractor(path): - import capa.features.extractors.ghidra.extractor - - extractor = capa.features.extractors.ghidra.extractor.GhidraFeatureExtractor(path) - - # overload the extractor so that the fixture exposes `extractor.path` - setattr(extractor, "path", path) - - return extractor - - def extract_global_features(extractor): features = collections.defaultdict(set) for feature, va in extractor.extract_global_features(): diff --git a/tests/test_ghidra_features.py b/tests/test_ghidra_features.py deleted file mode 100644 index ff8e6485a..000000000 --- a/tests/test_ghidra_features.py +++ /dev/null @@ -1,55 +0,0 @@ -import sys -import logging -import os.path -import binascii -import traceback - -import pytest - -try: - sys.path.append(os.path.dirname(__file__)) - import fixtures - from fixtures import * -finally: - sys.path.pop() - - -logger = logging.getLogger("test_ghidra_features") - - -# We need to skip the ghidra test if we cannot import ghidra modules, e.g., in GitHub CI. -ghidra_present: bool = False -try: - import ghidra.program.flatapi as flatapi - ghidraapi = flatapi.FlatProgramAPI(currentProgram) - - try: - current_program_test = ghidraapi.getCurrentProgram() - except RuntimeError as e: - logger.warning("Ghidra runtime not detected") - else: - ghidra_present = True -except ImportError: - pass - - -@pytest.mark.skipif(ghidra_present is False, reason="Skip ghidra tests if the ghidra Python API is not installed") -@fixtures.parametrize( - "sample,scope,feature,expected", - fixtures.FEATURE_PRESENCE_TESTS, - indirect=["sample", "scope"], -) -def test_ghidra_features(sample, scope, feature, expected): - fixtures.do_test_feature_presence(fixtures.get_ghidra_extractor, sample, scope, feature, expected) - - -@pytest.mark.skipif(ghidra_present is False, reason="Skip ghidra tests if the ghidra Python API is not installed") -@fixtures.parametrize( - "sample,scope,feature,expected", - fixtures.FEATURE_COUNT_TESTS, - indirect=["sample", "scope"], -) -def test_ghidra_feature_counts(sample, scope, feature, expected): - fixtures.do_test_feature_count(fixtures.get_ghidra_extractor, sample, scope, feature, expected) - - From c5f51e03f43aec06a858f9386ffe7d63e5ee4f5c Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Thu, 6 Jul 2023 01:27:37 -0700 Subject: [PATCH 15/46] ghidra: Add Global Feature Extraction (#1526) * Revert "colton: removed redundant imports & object, locally tested" This reverts commit 3da233dcad430d2af14b40e7651d997690a7336d. * removed redundant imports & objects, local test confirmation * linted with isort * linted with black * linted with pycodestyle * additional linting * rebasing to avoid merge conflicts --- CHANGELOG.md | 1 + capa/features/extractors/ghidra/global_.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec03dad34..a67cd74f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - + ### Bug Fixes - extractor: update vivisect Arch extraction #1334 @mr-tz - extractor: avoid Binary Ninja exception when analyzing certain files #1441 @xusheng6 diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py index 33a1237c2..d4026eaf0 100644 --- a/capa/features/extractors/ghidra/global_.py +++ b/capa/features/extractors/ghidra/global_.py @@ -14,7 +14,7 @@ def extract_os() -> Iterator[Tuple[Feature, Address]]: - format_name: str = currentProgram.getExecutableFormat() + format_name: str = currentProgram.getExecutableFormat() # currentProgram: static Ghidra variable if "PE" in format_name: yield OS(OS_WINDOWS), NO_ADDRESS From 1f631b3ed16f3f857ce74b49313fa6401110171a Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Thu, 6 Jul 2023 15:42:04 -0700 Subject: [PATCH 16/46] bump min Python3 version to 3.8 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c4b2d5e01..abaddb999 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -144,7 +144,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.11"] + python-version: ["3.8", "3.11"] java-version: ["17"] gradle-version: ["7.3"] ghidra-version: ["10.3"] From 51ffb1d75cc3d42716a22851dd1d660bbb09cd5c Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Thu, 6 Jul 2023 17:05:08 -0700 Subject: [PATCH 17/46] Add Ghidra File Feature Extraction (#1564) Implement Ghidra backend file feature extraction --- capa/features/extractors/ghidra/extractor.py | 14 ++ capa/features/extractors/ghidra/file.py | 201 +++++++++++++++++++ capa/features/extractors/ghidra/global_.py | 8 + capa/features/extractors/ghidra/helpers.py | 60 ++++++ capa/main.py | 13 +- 5 files changed, 292 insertions(+), 4 deletions(-) create mode 100644 capa/features/extractors/ghidra/helpers.py diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py index 65b067064..b4441bf96 100644 --- a/capa/features/extractors/ghidra/extractor.py +++ b/capa/features/extractors/ghidra/extractor.py @@ -2,15 +2,29 @@ import contextlib from typing import List, Tuple, Iterator +import ghidra + import capa.features.extractors.ghidra.global_ from capa.features.common import Feature from capa.features.address import Address, AbsoluteVirtualAddress from capa.features.extractors.base_extractor import FeatureExtractor +currentProgram: ghidra.program.database.ProgramDB + class GhidraFeatureExtractor(FeatureExtractor): def __init__(self): super().__init__() self.global_features: List[Tuple[Feature, Address]] = [] + self.global_features.extend(capa.features.extractors.ghidra.file.extract_file_format()) self.global_features.extend(capa.features.extractors.ghidra.global_.extract_os()) self.global_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) + + def get_base_address(self): + return AbsoluteVirtualAddress(currentProgram.getImageBase().getOffset()) + + def extract_global_features(self): + yield from self.global_features + + def extract_file_features(self): + yield from capa.features.extractors.ghidra.file.extract_features() diff --git a/capa/features/extractors/ghidra/file.py b/capa/features/extractors/ghidra/file.py index e69de29bb..a37d54153 100644 --- a/capa/features/extractors/ghidra/file.py +++ b/capa/features/extractors/ghidra/file.py @@ -0,0 +1,201 @@ +# Copyright (C) 2020 Mandiant, Inc. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: [package root]/LICENSE.txt +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and limitations under the License. + +import struct +from typing import Tuple, Iterator + +import ghidra +from ghidra.program.model.symbol import SourceType, SymbolType + +import capa.features.extractors.common +import capa.features.extractors.helpers +import capa.features.extractors.strings +import capa.features.extractors.ghidra.helpers +from capa.features.file import Export, Import, Section, FunctionName +from capa.features.common import FORMAT_PE, FORMAT_ELF, Format, String, Feature, Characteristic +from capa.features.address import NO_ADDRESS, Address, FileOffsetAddress, AbsoluteVirtualAddress + +currentProgram: ghidra.program.database.ProgramDB + +MAX_OFFSET_PE_AFTER_MZ = 0x200 + + +def check_segment_for_pe() -> Iterator[Tuple[int, int]]: + """check segment for embedded PE + + adapted for Ghidra from: + https://github.com/vivisect/vivisect/blob/91e8419a861f4977https://github.com/vivisect/vivisect/blob/91e8419a861f49779f18316f155311967e696836/PE/carve.py#L259f18316f155311967e696836/PE/carve.py#L25 + """ + + mz_xor = [ + ( + capa.features.extractors.helpers.xor_static(b"MZ", i), + capa.features.extractors.helpers.xor_static(b"PE", i), + i, + ) + for i in range(256) + ] + + todo = [] + for mzx, pex, i in mz_xor: + # find all segment offsets containing XOR'd "MZ" bytes + off: ghidra.program.model.address.GenericAddress + for off in capa.features.extractors.ghidra.helpers.find_byte_sequence(mzx): + todo.append((off, mzx, pex, i)) + + seg_max = currentProgram.getMaxAddress() + while len(todo): + off, mzx, pex, i = todo.pop() + + # MZ header has one field we will check e_lfanew is at 0x3c + e_lfanew = off.add(0x3C) + + if seg_max.getOffset() < (e_lfanew.getOffset() + 4): + continue + + e_lfanew_bytes = capa.features.extractors.ghidra.helpers.get_bytes(e_lfanew, 4) + newoff = struct.unpack(" MAX_OFFSET_PE_AFTER_MZ: + continue + + peoff = off.add(newoff) + if seg_max.getOffset() < (peoff.getOffset() + 2): + continue + + pe_bytes = capa.features.extractors.ghidra.helpers.get_bytes(peoff, 2) + if pe_bytes == pex: + yield off.getOffset(), i + + +def extract_file_embedded_pe() -> Iterator[Tuple[Feature, Address]]: + """extract embedded PE features""" + + for ea, _ in check_segment_for_pe(): + yield Characteristic("embedded pe"), FileOffsetAddress(ea) + + +def extract_file_export_names() -> Iterator[Tuple[Feature, Address]]: + """extract function exports""" + st = currentProgram.getSymbolTable() + for addr in st.getExternalEntryPointIterator(): + yield Export(st.getPrimarySymbol(addr).getName()), AbsoluteVirtualAddress(addr.getOffset()) + + +def extract_file_import_names() -> Iterator[Tuple[Feature, Address]]: + """extract function imports + + 1. imports by ordinal: + - modulename.#ordinal + + 2. imports by name, results in two features to support importname-only + matching: + - modulename.importname + - importname + """ + + for f in currentProgram.getFunctionManager().getExternalFunctions(): + for r in f.getSymbol().getReferences(): + if r.getReferenceType().isData(): + addr = r.getFromAddress().getOffset() # gets pointer to fake external addr + + fstr = f.toString().split("::") # format: MODULE.dll::import / MODULE::Ordinal_* + if "Ordinal_" in fstr[1]: + fstr[1] = f"#{fstr[1].split('_')[1]}" + + for name in capa.features.extractors.helpers.generate_symbols(fstr[0][:-4], fstr[1]): + yield Import(name), AbsoluteVirtualAddress(addr) + + +def extract_file_section_names() -> Iterator[Tuple[Feature, Address]]: + """extract section names""" + + for block in currentProgram.getMemory().getBlocks(): + yield Section(block.getName()), AbsoluteVirtualAddress(block.getStart().getOffset()) + + +def extract_file_strings() -> Iterator[Tuple[Feature, Address]]: + """extract ASCII and UTF-16 LE strings""" + + for block in currentProgram.getMemory().getBlocks(): + if block.isInitialized(): + p_bytes = capa.features.extractors.ghidra.helpers.get_block_bytes(block) + if len(p_bytes) == 0: + break + + for s in capa.features.extractors.strings.extract_ascii_strings(p_bytes): + offset = block.getStart().getOffset() + s.offset + yield String(s.s), FileOffsetAddress(offset) + + for s in capa.features.extractors.strings.extract_unicode_strings(p_bytes): + offset = block.getStart().getOffset() + s.offset + yield String(s.s), FileOffsetAddress(offset) + + +def extract_file_function_names() -> Iterator[Tuple[Feature, Address]]: + """ + extract the names of statically-linked library functions. + """ + + for sym in currentProgram.getSymbolTable().getAllSymbols(True): + # .isExternal() misses more than this config for the function symbols + if sym.getSymbolType() == SymbolType.FUNCTION and sym.getSource() == SourceType.ANALYSIS and sym.isGlobal(): + name = sym.getName() # starts to resolve names based on Ghidra's FidDB + if name.startswith("FID_conflict:"): # format: FID_conflict: + name = name[13:] + addr = AbsoluteVirtualAddress(sym.getAddress().getOffset()) + yield FunctionName(name), addr + if name.startswith("_"): + # some linkers may prefix linked routines with a `_` to avoid name collisions. + # extract features for both the mangled and un-mangled representations. + # e.g. `_fwrite` -> `fwrite` + # see: https://stackoverflow.com/a/2628384/87207 + yield FunctionName(name[1:]), addr + + +def extract_file_format() -> Iterator[Tuple[Feature, Address]]: + ef = currentProgram.getExecutableFormat() + if "PE" in ef: + yield Format(FORMAT_PE), NO_ADDRESS + elif "ELF" in ef: + yield Format(FORMAT_ELF), NO_ADDRESS + elif "Raw" in ef: + # no file type to return when processing a binary file, but we want to continue processing + return + else: + raise NotImplementedError(f"unexpected file format: {ef}") + + +def extract_features() -> Iterator[Tuple[Feature, Address]]: + """extract file features""" + for file_handler in FILE_HANDLERS: + for feature, addr in file_handler(): + yield feature, addr + + +FILE_HANDLERS = ( + extract_file_embedded_pe, + extract_file_export_names, + extract_file_import_names, + extract_file_section_names, + extract_file_strings, + extract_file_function_names, + extract_file_format, +) + + +def main(): + """ """ + import pprint + + pprint.pprint(list(extract_features())) + + +if __name__ == "__main__": + main() diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py index d4026eaf0..4db794c87 100644 --- a/capa/features/extractors/ghidra/global_.py +++ b/capa/features/extractors/ghidra/global_.py @@ -1,3 +1,11 @@ +# Copyright (C) 2020 Mandiant, Inc. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: [package root]/LICENSE.txt +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and limitations under the License. + import logging import contextlib from io import BytesIO diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py new file mode 100644 index 000000000..dac115472 --- /dev/null +++ b/capa/features/extractors/ghidra/helpers.py @@ -0,0 +1,60 @@ +# Copyright (C) 2020 Mandiant, Inc. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: [package root]/LICENSE.txt +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and limitations under the License. +from typing import Any, Dict, Tuple, Iterator, Optional + +import ghidra + +currentProgram: ghidra.program.database.ProgramDB + + +def find_byte_sequence(seq: bytes) -> Iterator[int]: + """yield all ea of a given byte sequence + + args: + seq: bytes to search e.g. b"\x01\x03" + """ + seqstr = "".join([f"\\x{b:02x}" for b in seq]) + # .add(1) to avoid false positives on regular PE files + ea = findBytes(currentProgram.getMinAddress().add(1), seqstr, 1, 1) # type: ignore [name-defined] + for e in ea: + yield e + + +def get_bytes(addr: ghidra.program.model.address.Address, length: int) -> bytes: + """yield length bytes at addr + + args: + addr: Address to begin pull from + length: length of bytes to pull + """ + + bytez = b"" + try: + signed_ints = getBytes(addr, length) # type: ignore [name-defined] + for b in signed_ints: + bytez = bytez + (b & 0xFF).to_bytes(1, "little") + return bytez + except RuntimeError: + return bytez + + +def get_block_bytes(block: ghidra.program.model.mem.MemoryBlock) -> bytes: + """yield all bytes in a given block + + args: + block: MemoryBlock to pull from + """ + + bytez = b"" + try: + signed_ints = getBytes(block.getStart(), block.getEnd().getOffset() - block.getStart().getOffset()) # type: ignore [name-defined] + for b in signed_ints: + bytez = bytez + (b & 0xFF).to_bytes(1, "little") + return bytez + except RuntimeError: + return bytez diff --git a/capa/main.py b/capa/main.py index 65e9c81e8..06f097a27 100644 --- a/capa/main.py +++ b/capa/main.py @@ -1004,7 +1004,7 @@ def handle_common_args(args): # if isinstance(sys.stdout, io.TextIOWrapper): # sys.stdout.reconfigure(...) sys.stdout.reconfigure(encoding="utf-8") - colorama.just_fix_windows_console() + colorama.just_fix_windows_console() # type: ignore [attr-defined] if args.color == "always": colorama.init(strip=False) @@ -1341,6 +1341,7 @@ def ida_main(): def ghidra_main(): import capa.rules + import capa.features.extractors.ghidra.file # import capa.render.default # import capa.features.extractors.ghidra.extractor @@ -1357,9 +1358,9 @@ def ghidra_main(): logger.debug(" https://github.com/mandiant/capa-rules") logger.debug("-" * 80) - rules_path = os.path.join(get_default_root(), "rules") - logger.debug("rule path: %s", rules_path) - rules = get_rules([rules_path]) + # rules_path = os.path.join(get_default_root(), "rules") + # logger.debug("rule path: %s", rules_path) + # rules = get_rules([rules_path]) # temp test for OS & ARCH extractions globl_features: List[Tuple[Feature, Address]] = [] @@ -1367,6 +1368,10 @@ def ghidra_main(): globl_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) print(globl_features) + file_features: List[Tuple[Feature, Address]] = [] + file_features.extend(capa.features.extractors.ghidra.file.extract_features()) + print(file_features) + def is_runtime_ida(): try: From 97c20056610701636994b391d2160ffc9f030773 Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Wed, 12 Jul 2023 07:58:35 -0700 Subject: [PATCH 18/46] Ghidra: Function Feature Extraction (#1597) * save progress * implement loop detection * implement recursive call detection * lint repo * fix python/java import errors * simplify recursion detection * streamline loop detection, fix helper function signature --- capa/features/extractors/ghidra/file.py | 2 - capa/features/extractors/ghidra/function.py | 72 +++++++++++++++++++++ capa/features/extractors/ghidra/helpers.py | 21 +++++- capa/main.py | 22 ++++--- 4 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 capa/features/extractors/ghidra/function.py diff --git a/capa/features/extractors/ghidra/file.py b/capa/features/extractors/ghidra/file.py index a37d54153..86c0421ed 100644 --- a/capa/features/extractors/ghidra/file.py +++ b/capa/features/extractors/ghidra/file.py @@ -126,8 +126,6 @@ def extract_file_strings() -> Iterator[Tuple[Feature, Address]]: for block in currentProgram.getMemory().getBlocks(): if block.isInitialized(): p_bytes = capa.features.extractors.ghidra.helpers.get_block_bytes(block) - if len(p_bytes) == 0: - break for s in capa.features.extractors.strings.extract_ascii_strings(p_bytes): offset = block.getStart().getOffset() + s.offset diff --git a/capa/features/extractors/ghidra/function.py b/capa/features/extractors/ghidra/function.py new file mode 100644 index 000000000..ca82a03ad --- /dev/null +++ b/capa/features/extractors/ghidra/function.py @@ -0,0 +1,72 @@ +# Copyright (C) 2020 Mandiant, Inc. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: [package root]/LICENSE.txt +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and limitations under the License. +from typing import Tuple, Iterator + +import ghidra +from ghidra.program.model.block import BasicBlockModel, SimpleBlockIterator + +import capa.features.extractors.ghidra.helpers +from capa.features.common import Feature, Characteristic +from capa.features.address import Address, AbsoluteVirtualAddress +from capa.features.extractors import loops +from capa.features.extractors.base_extractor import FunctionHandle + +currentProgram: ghidra.program.database.ProgramDB +monitor: ghidra.util.task.TaskMonitor + + +def extract_function_calls_to(fh: ghidra.program.database.function.FunctionDB): + """extract callers to a function""" + for ref in fh.getSymbol().getReferences(): + if ref.getReferenceType().isCall(): + yield Characteristic("calls to"), AbsoluteVirtualAddress(ref.getFromAddress().getOffset()) + + +def extract_function_loop(fh: ghidra.program.database.function.FunctionDB): + edges = [] + + for block in SimpleBlockIterator(BasicBlockModel(currentProgram), fh.getBody(), monitor): + dests = block.getDestinations(monitor) + s_addrs = block.getStartAddresses() + + while dests.hasNext(): # For loop throws Python TypeError + for addr in s_addrs: + edges.append((addr.getOffset(), dests.next().getDestinationAddress().getOffset())) + + if loops.has_loop(edges): + yield Characteristic("loop"), AbsoluteVirtualAddress(fh.getEntryPoint().getOffset()) + + +def extract_recursive_call(fh: ghidra.program.database.function.FunctionDB): + for f in fh.getCalledFunctions(monitor): + if f.getEntryPoint().getOffset() == fh.getEntryPoint().getOffset(): + yield Characteristic("recursive call"), AbsoluteVirtualAddress(fh.getEntryPoint().getOffset()) + + +def extract_features(fh: ghidra.program.database.function.FunctionDB) -> Iterator[Tuple[Feature, Address]]: + for func_handler in FUNCTION_HANDLERS: + for feature, addr in func_handler(fh): + yield feature, addr + + +FUNCTION_HANDLERS = (extract_function_calls_to, extract_function_loop, extract_recursive_call) + + +def main(): + """ """ + features = [] + for fhandle in capa.features.extractors.ghidra.helpers.get_function_symbols(): + features.extend(list(extract_features(fhandle))) + + import pprint + + pprint.pprint(features) + + +if __name__ == "__main__": + main() diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py index dac115472..26518ca5f 100644 --- a/capa/features/extractors/ghidra/helpers.py +++ b/capa/features/extractors/ghidra/helpers.py @@ -8,10 +8,20 @@ from typing import Any, Dict, Tuple, Iterator, Optional import ghidra +from ghidra.program.model.symbol import SymbolType currentProgram: ghidra.program.database.ProgramDB +def fix_byte(b: int) -> bytes: + """Transform signed ints from Java into bytes for Python + + args: + b: signed int returned from Java processing + """ + return (b & 0xFF).to_bytes(1, "little") + + def find_byte_sequence(seq: bytes) -> Iterator[int]: """yield all ea of a given byte sequence @@ -37,7 +47,7 @@ def get_bytes(addr: ghidra.program.model.address.Address, length: int) -> bytes: try: signed_ints = getBytes(addr, length) # type: ignore [name-defined] for b in signed_ints: - bytez = bytez + (b & 0xFF).to_bytes(1, "little") + bytez = bytez + fix_byte(b) return bytez except RuntimeError: return bytez @@ -54,7 +64,14 @@ def get_block_bytes(block: ghidra.program.model.mem.MemoryBlock) -> bytes: try: signed_ints = getBytes(block.getStart(), block.getEnd().getOffset() - block.getStart().getOffset()) # type: ignore [name-defined] for b in signed_ints: - bytez = bytez + (b & 0xFF).to_bytes(1, "little") + bytez = bytez + fix_byte(b) return bytez except RuntimeError: return bytez + + +def get_function_symbols() -> Iterator[ghidra.program.database.function.FunctionDB]: + """yield all non-external function symbols""" + + for f in currentProgram.getFunctionManager().getFunctionsNoStubs(True): + yield f diff --git a/capa/main.py b/capa/main.py index 0d381ce66..a1e4537a0 100644 --- a/capa/main.py +++ b/capa/main.py @@ -1002,7 +1002,7 @@ def handle_common_args(args): # if isinstance(sys.stdout, io.TextIOWrapper): # sys.stdout.reconfigure(...) sys.stdout.reconfigure(encoding="utf-8") - colorama.just_fix_windows_console() # type: ignore [attr-defined] + colorama.just_fix_windows_console() if args.color == "always": colorama.init(strip=False) @@ -1344,6 +1344,8 @@ def ghidra_main(): # import capa.render.default # import capa.features.extractors.ghidra.extractor import capa.features.extractors.ghidra.global_ + import capa.features.extractors.ghidra.helpers + import capa.features.extractors.ghidra.function from capa.features.common import Feature logging.basicConfig(level=logging.INFO) @@ -1360,15 +1362,17 @@ def ghidra_main(): # logger.debug("rule path: %s", rules_path) # rules = get_rules([rules_path]) - # temp test for OS & ARCH extractions - globl_features: List[Tuple[Feature, Address]] = [] - globl_features.extend(capa.features.extractors.ghidra.global_.extract_os()) - globl_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) - print(globl_features) + # temp test for ghidra CI + ghidra_features: List[Tuple[Feature, Address]] = [] + ghidra_features.extend(capa.features.extractors.ghidra.global_.extract_os()) + ghidra_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) + ghidra_features.extend(capa.features.extractors.ghidra.file.extract_features()) + for fhandle in capa.features.extractors.ghidra.helpers.get_function_symbols(): + ghidra_features.extend(list(capa.features.extractors.ghidra.function.extract_features(fhandle))) - file_features: List[Tuple[Feature, Address]] = [] - file_features.extend(capa.features.extractors.ghidra.file.extract_features()) - print(file_features) + import pprint + + pprint.pprint(ghidra_features) def is_runtime_ida(): From 94aaaa297d4fe61a02ade5055d8b1a3afae885e6 Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Thu, 13 Jul 2023 18:16:11 +0000 Subject: [PATCH 19/46] remove stale is_runtime_ida function --- capa/main.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/capa/main.py b/capa/main.py index 9724f314a..ff73c3ca8 100644 --- a/capa/main.py +++ b/capa/main.py @@ -1368,15 +1368,6 @@ def ghidra_main(): pprint.pprint(ghidra_features) -def is_runtime_ida(): - try: - import idc - except ImportError: - return False - else: - return True - - def is_runtime_ghidra(): try: import ghidra.program.flatapi From 68caece2fab1ecdad6d9c07bc4dc9cdd5afcc9a5 Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Thu, 13 Jul 2023 18:49:52 +0000 Subject: [PATCH 20/46] fix linting errors --- capa/features/extractors/ghidra/extractor.py | 13 ++++++++---- capa/features/extractors/ghidra/file.py | 21 +++++++++----------- capa/features/extractors/ghidra/function.py | 14 +++++-------- capa/features/extractors/ghidra/global_.py | 16 ++++++--------- capa/features/extractors/ghidra/helpers.py | 19 +++++++----------- capa/helpers.py | 4 ++++ capa/main.py | 13 ++---------- 7 files changed, 42 insertions(+), 58 deletions(-) diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py index b4441bf96..af5047374 100644 --- a/capa/features/extractors/ghidra/extractor.py +++ b/capa/features/extractors/ghidra/extractor.py @@ -1,6 +1,11 @@ -import logging -import contextlib -from typing import List, Tuple, Iterator +# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: [package root]/LICENSE.txt +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and limitations under the License. +from typing import List, Tuple import ghidra @@ -21,7 +26,7 @@ def __init__(self): self.global_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) def get_base_address(self): - return AbsoluteVirtualAddress(currentProgram.getImageBase().getOffset()) + return AbsoluteVirtualAddress(currentProgram.getImageBase().getOffset()) # type: ignore [name-defined] # noqa: F821 def extract_global_features(self): yield from self.global_features diff --git a/capa/features/extractors/ghidra/file.py b/capa/features/extractors/ghidra/file.py index 86c0421ed..8845354f1 100644 --- a/capa/features/extractors/ghidra/file.py +++ b/capa/features/extractors/ghidra/file.py @@ -1,11 +1,10 @@ -# Copyright (C) 2020 Mandiant, Inc. All Rights Reserved. +# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: [package root]/LICENSE.txt # Unless required by applicable law or agreed to in writing, software distributed under the License # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and limitations under the License. - import struct from typing import Tuple, Iterator @@ -20,8 +19,6 @@ from capa.features.common import FORMAT_PE, FORMAT_ELF, Format, String, Feature, Characteristic from capa.features.address import NO_ADDRESS, Address, FileOffsetAddress, AbsoluteVirtualAddress -currentProgram: ghidra.program.database.ProgramDB - MAX_OFFSET_PE_AFTER_MZ = 0x200 @@ -48,7 +45,7 @@ def check_segment_for_pe() -> Iterator[Tuple[int, int]]: for off in capa.features.extractors.ghidra.helpers.find_byte_sequence(mzx): todo.append((off, mzx, pex, i)) - seg_max = currentProgram.getMaxAddress() + seg_max = currentProgram.getMaxAddress() # type: ignore [name-defined] # noqa: F821 while len(todo): off, mzx, pex, i = todo.pop() @@ -83,7 +80,7 @@ def extract_file_embedded_pe() -> Iterator[Tuple[Feature, Address]]: def extract_file_export_names() -> Iterator[Tuple[Feature, Address]]: """extract function exports""" - st = currentProgram.getSymbolTable() + st = currentProgram.getSymbolTable() # type: ignore [name-defined] # noqa: F821 for addr in st.getExternalEntryPointIterator(): yield Export(st.getPrimarySymbol(addr).getName()), AbsoluteVirtualAddress(addr.getOffset()) @@ -100,7 +97,7 @@ def extract_file_import_names() -> Iterator[Tuple[Feature, Address]]: - importname """ - for f in currentProgram.getFunctionManager().getExternalFunctions(): + for f in currentProgram.getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 for r in f.getSymbol().getReferences(): if r.getReferenceType().isData(): addr = r.getFromAddress().getOffset() # gets pointer to fake external addr @@ -116,14 +113,14 @@ def extract_file_import_names() -> Iterator[Tuple[Feature, Address]]: def extract_file_section_names() -> Iterator[Tuple[Feature, Address]]: """extract section names""" - for block in currentProgram.getMemory().getBlocks(): + for block in currentProgram.getMemory().getBlocks(): # type: ignore [name-defined] # noqa: F821 yield Section(block.getName()), AbsoluteVirtualAddress(block.getStart().getOffset()) def extract_file_strings() -> Iterator[Tuple[Feature, Address]]: """extract ASCII and UTF-16 LE strings""" - for block in currentProgram.getMemory().getBlocks(): + for block in currentProgram.getMemory().getBlocks(): # type: ignore [name-defined] # noqa: F821 if block.isInitialized(): p_bytes = capa.features.extractors.ghidra.helpers.get_block_bytes(block) @@ -141,7 +138,7 @@ def extract_file_function_names() -> Iterator[Tuple[Feature, Address]]: extract the names of statically-linked library functions. """ - for sym in currentProgram.getSymbolTable().getAllSymbols(True): + for sym in currentProgram.getSymbolTable().getAllSymbols(True): # type: ignore [name-defined] # noqa: F821 # .isExternal() misses more than this config for the function symbols if sym.getSymbolType() == SymbolType.FUNCTION and sym.getSource() == SourceType.ANALYSIS and sym.isGlobal(): name = sym.getName() # starts to resolve names based on Ghidra's FidDB @@ -158,7 +155,7 @@ def extract_file_function_names() -> Iterator[Tuple[Feature, Address]]: def extract_file_format() -> Iterator[Tuple[Feature, Address]]: - ef = currentProgram.getExecutableFormat() + ef = currentProgram.getExecutableFormat() # type: ignore [name-defined] # noqa: F821 if "PE" in ef: yield Format(FORMAT_PE), NO_ADDRESS elif "ELF" in ef: @@ -192,7 +189,7 @@ def main(): """ """ import pprint - pprint.pprint(list(extract_features())) + pprint.pprint(list(extract_features())) # noqa: T203 if __name__ == "__main__": diff --git a/capa/features/extractors/ghidra/function.py b/capa/features/extractors/ghidra/function.py index ca82a03ad..98d4ee9ba 100644 --- a/capa/features/extractors/ghidra/function.py +++ b/capa/features/extractors/ghidra/function.py @@ -1,4 +1,4 @@ -# Copyright (C) 2020 Mandiant, Inc. All Rights Reserved. +# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: [package root]/LICENSE.txt @@ -14,10 +14,6 @@ from capa.features.common import Feature, Characteristic from capa.features.address import Address, AbsoluteVirtualAddress from capa.features.extractors import loops -from capa.features.extractors.base_extractor import FunctionHandle - -currentProgram: ghidra.program.database.ProgramDB -monitor: ghidra.util.task.TaskMonitor def extract_function_calls_to(fh: ghidra.program.database.function.FunctionDB): @@ -30,8 +26,8 @@ def extract_function_calls_to(fh: ghidra.program.database.function.FunctionDB): def extract_function_loop(fh: ghidra.program.database.function.FunctionDB): edges = [] - for block in SimpleBlockIterator(BasicBlockModel(currentProgram), fh.getBody(), monitor): - dests = block.getDestinations(monitor) + for block in SimpleBlockIterator(BasicBlockModel(currentProgram), fh.getBody(), monitor): # type: ignore [name-defined] # noqa: F821 + dests = block.getDestinations(monitor) # type: ignore [name-defined] # noqa: F821 s_addrs = block.getStartAddresses() while dests.hasNext(): # For loop throws Python TypeError @@ -43,7 +39,7 @@ def extract_function_loop(fh: ghidra.program.database.function.FunctionDB): def extract_recursive_call(fh: ghidra.program.database.function.FunctionDB): - for f in fh.getCalledFunctions(monitor): + for f in fh.getCalledFunctions(monitor): # type: ignore [name-defined] # noqa: F821 if f.getEntryPoint().getOffset() == fh.getEntryPoint().getOffset(): yield Characteristic("recursive call"), AbsoluteVirtualAddress(fh.getEntryPoint().getOffset()) @@ -65,7 +61,7 @@ def main(): import pprint - pprint.pprint(features) + pprint.pprint(features) # noqa: T203 if __name__ == "__main__": diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py index 4db794c87..bf78baece 100644 --- a/capa/features/extractors/ghidra/global_.py +++ b/capa/features/extractors/ghidra/global_.py @@ -1,36 +1,32 @@ -# Copyright (C) 2020 Mandiant, Inc. All Rights Reserved. +# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: [package root]/LICENSE.txt # Unless required by applicable law or agreed to in writing, software distributed under the License # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and limitations under the License. - import logging import contextlib from io import BytesIO from typing import Tuple, Iterator -import ghidra - import capa.features.extractors.elf from capa.features.common import OS, ARCH_I386, ARCH_AMD64, OS_WINDOWS, Arch, Feature from capa.features.address import NO_ADDRESS, Address logger = logging.getLogger(__name__) -currentProgram: ghidra.program.database.ProgramDB def extract_os() -> Iterator[Tuple[Feature, Address]]: - format_name: str = currentProgram.getExecutableFormat() # currentProgram: static Ghidra variable + format_name: str = currentProgram.getExecutableFormat() # type: ignore [name-defined] # noqa: F821 if "PE" in format_name: yield OS(OS_WINDOWS), NO_ADDRESS elif "ELF" in format_name: - program_memory = currentProgram.getMemory() # ghidra.program.database.mem.MemoryMapDB - fbytes_list = program_memory.getAllFileBytes() # java.util.List - fbytes = fbytes_list[0] # ghidra.program.database.mem.FileBytes + program_memory = currentProgram.getMemory() # type: ignore [name-defined] # noqa: F821 + fbytes_list = program_memory.getAllFileBytes() + fbytes = fbytes_list[0] # Java likes to return signed ints, so we must convert them # back into unsigned bytes manually and write to BytesIO @@ -61,7 +57,7 @@ def extract_os() -> Iterator[Tuple[Feature, Address]]: def extract_arch() -> Iterator[Tuple[Feature, Address]]: - lang_id = currentProgram.getMetadata().get("Language ID") + lang_id = currentProgram.getMetadata().get("Language ID") # type: ignore [name-defined] # noqa: F821 if "x86" in lang_id and "64" in lang_id: yield Arch(ARCH_AMD64), NO_ADDRESS diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py index 26518ca5f..7f4aa44f3 100644 --- a/capa/features/extractors/ghidra/helpers.py +++ b/capa/features/extractors/ghidra/helpers.py @@ -1,16 +1,13 @@ -# Copyright (C) 2020 Mandiant, Inc. All Rights Reserved. +# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: [package root]/LICENSE.txt # Unless required by applicable law or agreed to in writing, software distributed under the License # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and limitations under the License. -from typing import Any, Dict, Tuple, Iterator, Optional +from typing import Iterator import ghidra -from ghidra.program.model.symbol import SymbolType - -currentProgram: ghidra.program.database.ProgramDB def fix_byte(b: int) -> bytes: @@ -30,9 +27,8 @@ def find_byte_sequence(seq: bytes) -> Iterator[int]: """ seqstr = "".join([f"\\x{b:02x}" for b in seq]) # .add(1) to avoid false positives on regular PE files - ea = findBytes(currentProgram.getMinAddress().add(1), seqstr, 1, 1) # type: ignore [name-defined] - for e in ea: - yield e + eas = findBytes(currentProgram.getMinAddress().add(1), seqstr, 1, 1) # type: ignore [name-defined] # noqa: F821 + yield from eas def get_bytes(addr: ghidra.program.model.address.Address, length: int) -> bytes: @@ -45,7 +41,7 @@ def get_bytes(addr: ghidra.program.model.address.Address, length: int) -> bytes: bytez = b"" try: - signed_ints = getBytes(addr, length) # type: ignore [name-defined] + signed_ints = getBytes(addr, length) # type: ignore [name-defined] # noqa: F821 for b in signed_ints: bytez = bytez + fix_byte(b) return bytez @@ -62,7 +58,7 @@ def get_block_bytes(block: ghidra.program.model.mem.MemoryBlock) -> bytes: bytez = b"" try: - signed_ints = getBytes(block.getStart(), block.getEnd().getOffset() - block.getStart().getOffset()) # type: ignore [name-defined] + signed_ints = getBytes(block.getStart(), block.getEnd().getOffset() - block.getStart().getOffset()) # type: ignore [name-defined] # noqa: F821 for b in signed_ints: bytez = bytez + fix_byte(b) return bytez @@ -73,5 +69,4 @@ def get_block_bytes(block: ghidra.program.model.mem.MemoryBlock) -> bytes: def get_function_symbols() -> Iterator[ghidra.program.database.function.FunctionDB]: """yield all non-external function symbols""" - for f in currentProgram.getFunctionManager().getFunctionsNoStubs(True): - yield f + yield from currentProgram.getFunctionManager().getFunctionsNoStubs(True) # type: ignore [name-defined] # noqa: F821 diff --git a/capa/helpers.py b/capa/helpers.py index 92f26c3d1..69c7ccf2a 100644 --- a/capa/helpers.py +++ b/capa/helpers.py @@ -43,6 +43,10 @@ def is_runtime_ida(): return importlib.util.find_spec("idc") is not None +def is_runtime_ghidra(): + return importlib.util.find_spec("ghidra.program.flatapi") is not None + + def assert_never(value) -> NoReturn: # careful: python -O will remove this assertion. # but this is only used for type checking, so it's ok. diff --git a/capa/main.py b/capa/main.py index ff73c3ca8..ff418578c 100644 --- a/capa/main.py +++ b/capa/main.py @@ -1365,22 +1365,13 @@ def ghidra_main(): import pprint - pprint.pprint(ghidra_features) - - -def is_runtime_ghidra(): - try: - import ghidra.program.flatapi - except ImportError: - return False - else: - return True + pprint.pprint(ghidra_features) # noqa: T203 if __name__ == "__main__": if capa.helpers.is_runtime_ida(): ida_main() - elif is_runtime_ghidra(): + elif capa.helpers.is_runtime_ghidra(): ghidra_main() else: sys.exit(main()) From 6fa7f248183c37de544c9bad63ce8569fe786a3f Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Mon, 17 Jul 2023 08:00:03 -0700 Subject: [PATCH 21/46] Ghidra: Basic Block Feature Extraction (#1637) * save progress * implement loop detection * implement recursive call detection * lint repo * fix python/java import errors * simplify recursion detection * implement tight loop extraction * streamline loop detection, fix helper function signature * begin stackstring extraction * implement is_mov_imm_to_stack() * implement stackstring extraction, fixture test passing * clean & lint, pass fixture tests * temp: resolve linting issues * temp: fix linting issues * implement reviewed changes, simplify functions * fix tight loop extraction --- capa/features/extractors/ghidra/basicblock.py | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 capa/features/extractors/ghidra/basicblock.py diff --git a/capa/features/extractors/ghidra/basicblock.py b/capa/features/extractors/ghidra/basicblock.py new file mode 100644 index 000000000..ddd241654 --- /dev/null +++ b/capa/features/extractors/ghidra/basicblock.py @@ -0,0 +1,147 @@ +# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: [package root]/LICENSE.txt +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and limitations under the License. + +import string +import struct +from typing import Tuple, Iterator + +import ghidra +from ghidra.program.model.lang import OperandType +from ghidra.program.model.block import BasicBlockModel, SimpleBlockIterator + +import capa.features.extractors.ghidra.helpers +from capa.features.common import Feature, Characteristic +from capa.features.address import Address, AbsoluteVirtualAddress +from capa.features.basicblock import BasicBlock +from capa.features.extractors.helpers import MIN_STACKSTRING_LEN + +listing = currentProgram.getListing() # type: ignore [name-defined] # noqa: F821 + + +def get_printable_len(op: ghidra.program.model.scalar.Scalar) -> int: + """Return string length if all operand bytes are ascii or utf16-le printable""" + op_bit_len = op.bitLength() + op_byte_len = op_bit_len // 8 + op_val = op.getValue() + + if op_bit_len == 8: + chars = struct.pack(" bool: + """verify instruction moves immediate onto stack""" + + # Ghidra will Bitwise OR the OperandTypes to assign multiple + # i.e., the first operand is a stackvar (dynamically allocated), + # and the second is a scalar value (single int/char/float/etc.) + mov_its_ops = [(OperandType.ADDRESS | OperandType.DYNAMIC), OperandType.SCALAR] + found = False + + # MOV dword ptr [EBP + local_*], 0x65 + if insn.getMnemonicString().startswith("MOV"): + found = all(insn.getOperandType(i) == mov_its_ops[i] for i in range(2)) + + return found + + +def bb_contains_stackstring(bb: ghidra.program.model.block.CodeBlock) -> bool: + """check basic block for stackstring indicators + + true if basic block contains enough moves of constant bytes to the stack + """ + count = 0 + for insn in listing.getInstructions(bb, True): + if is_mov_imm_to_stack(insn): + count += get_printable_len(insn.getScalar(1)) + if count > MIN_STACKSTRING_LEN: + return True + return False + + +def _bb_has_tight_loop(bb: ghidra.program.model.block.CodeBlock): + """ + parse tight loops, true if last instruction in basic block branches to bb start + """ + last_insn = listing.getInstructions(bb, False).next() # Reverse Ordered, first InstructionDB + + if last_insn.getFlowType().isJump(): + return last_insn.getAddress(0) == bb.getMinAddress() + + return False + + +def extract_bb_stackstring(bb: ghidra.program.model.block.CodeBlock) -> Iterator[Tuple[Feature, Address]]: + """extract stackstring indicators from basic block""" + if bb_contains_stackstring(bb): + yield Characteristic("stack string"), AbsoluteVirtualAddress(bb.getMinAddress().getOffset()) + + +def extract_bb_tight_loop(bb: ghidra.program.model.block.CodeBlock) -> Iterator[Tuple[Feature, Address]]: + """check basic block for tight loop indicators""" + if _bb_has_tight_loop(bb): + yield Characteristic("tight loop"), AbsoluteVirtualAddress(bb.getMinAddress().getOffset()) + + +BASIC_BLOCK_HANDLERS = ( + extract_bb_tight_loop, + extract_bb_stackstring, +) + + +def extract_features(bb: ghidra.program.model.block.CodeBlock) -> Iterator[Tuple[Feature, Address]]: + """ + extract features from the given basic block. + + args: + bb: the basic block to process. + + yields: + Tuple[Feature, int]: the features and their location found in this basic block. + """ + yield BasicBlock(), AbsoluteVirtualAddress(bb.getMinAddress().getOffset()) + for bb_handler in BASIC_BLOCK_HANDLERS: + for feature, addr in bb_handler(bb): + yield feature, addr + + +def main(): + features = [] + for fhandle in capa.features.extractors.ghidra.helpers.get_function_symbols(): + for bb in SimpleBlockIterator(BasicBlockModel(currentProgram), fhandle.getBody(), monitor): # type: ignore [name-defined] # noqa: F821 + features.extend(list(extract_features(bb))) + + import pprint + + pprint.pprint(features) # noqa: T203 + + +if __name__ == "__main__": + main() From 6287fbb95864dd4924539941dad3396c91780bad Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Tue, 8 Aug 2023 10:45:14 -0700 Subject: [PATCH 22/46] Ghidra insn features (#1670) * Implement Ghidra Instruction Feature Extraction --- capa/features/extractors/ghidra/helpers.py | 189 ++++++++- capa/features/extractors/ghidra/insn.py | 467 +++++++++++++++++++++ 2 files changed, 655 insertions(+), 1 deletion(-) create mode 100644 capa/features/extractors/ghidra/insn.py diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py index 7f4aa44f3..5bf6b9a8d 100644 --- a/capa/features/extractors/ghidra/helpers.py +++ b/capa/features/extractors/ghidra/helpers.py @@ -5,9 +5,14 @@ # Unless required by applicable law or agreed to in writing, software distributed under the License # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and limitations under the License. -from typing import Iterator +from typing import Dict, List, Iterator import ghidra +from ghidra.program.model.lang import OperandType +from ghidra.program.model.symbol import SourceType, SymbolType +from ghidra.program.model.address import AddressSpace + +import capa.features.extractors.helpers def fix_byte(b: int) -> bytes: @@ -70,3 +75,185 @@ def get_function_symbols() -> Iterator[ghidra.program.database.function.Function """yield all non-external function symbols""" yield from currentProgram.getFunctionManager().getFunctionsNoStubs(True) # type: ignore [name-defined] # noqa: F821 + + +def get_file_imports() -> Dict[int, List[str]]: + """get all import names & addrs""" + + import_dict: Dict[int, List[str]] = {} + + for f in currentProgram.getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 + for r in f.getSymbol().getReferences(): + if r.getReferenceType().isData(): + addr = r.getFromAddress().getOffset() # gets pointer to fake external addr + + fstr = f.toString().split("::") # format: MODULE.dll::import / MODULE::Ordinal_* + if "Ordinal_" in fstr[1]: + fstr[1] = f"#{fstr[1].split('_')[1]}" + + for name in capa.features.extractors.helpers.generate_symbols(fstr[0][:-4], fstr[1]): + import_dict.setdefault(addr, []).append(name) + + return import_dict + + +def get_file_externs() -> Dict[int, List[str]]: + """ + Gets function names & addresses of statically-linked library functions + + Ghidra's external namespace is mostly reserved for dynamically-linked + imports. Statically-linked functions are part of the global namespace. + Filtering on the type, source, and namespace of the symbols yield more + statically-linked library functions. + + Example: (PMA Lab 16-01.exe_) 7faafc7e4a5c736ebfee6abbbc812d80:0x407490 + - __aulldiv + - Note: See Symbol Table labels + """ + + extern_dict: Dict[int, List[str]] = {} + + for sym in currentProgram.getSymbolTable().getAllSymbols(True): # type: ignore [name-defined] # noqa: F821 + # .isExternal() misses more than this config for the function symbols + if sym.getSymbolType() == SymbolType.FUNCTION and sym.getSource() == SourceType.ANALYSIS and sym.isGlobal(): + name = sym.getName() # starts to resolve names based on Ghidra's FidDB + if name.startswith("FID_conflict:"): # format: FID_conflict: + name = name[13:] + extern_dict.setdefault(sym.getAddress().getOffset(), []).append(name) + if name.startswith("_"): + # some linkers may prefix linked routines with a `_` to avoid name collisions. + # extract features for both the mangled and un-mangled representations. + # e.g. `_fwrite` -> `fwrite` + # see: https://stackoverflow.com/a/2628384/87207 + extern_dict.setdefault(sym.getAddress().getOffset(), []).append(name[1:]) + + return extern_dict + + +def map_fake_import_addrs() -> Dict[int, List[int]]: + """ + Map ghidra's fake import entrypoints to their + real addresses + + Helps as many Ghidra Scripting API calls end up returning + these external (fake) addresses. + + Undocumented but intended Ghidra behavior: + - Import entryPoint fields are stored in the 'EXTERNAL:' AddressSpace. + 'getEntryPoint()' returns the entryPoint field, which is an offset + from the beginning of the assigned AddressSpace. In the case of externals, + they start from 1 and increment. + https://github.com/NationalSecurityAgency/ghidra/blob/26d4bd9104809747c21f2528cab8aba9aef9acd5/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/function/ExternalFunctionDBTest.java#L90 + + Example: (mimikatz.exe_) 5f66b82558ca92e54e77f216ef4c066c:0x473090 + - 0x473090 -> PTR_CreateServiceW_00473090 + - 'EXTERNAL:00000025' -> External Address (ghidra.program.model.address.SpecialAddress) + """ + fake_dict: Dict[int, List[int]] = {} + + for f in currentProgram.getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 + for r in f.getSymbol().getReferences(): + if r.getReferenceType().isData(): + fake_dict.setdefault(f.getEntryPoint().getOffset(), []).append(r.getFromAddress().getOffset()) + + return fake_dict + + +def get_external_locs() -> List[int]: + """ + Helps to discern external offsets from regular bytes when extracting + data. + + Ghidra behavior: + - Offsets that point to specific sections of external programs + i.e. library code. + - Stored in data, and pointed to by an absolute address + https://github.com/NationalSecurityAgency/ghidra/blob/26d4bd9104809747c21f2528cab8aba9aef9acd5/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/ExternalLocation.java#L25-30 + + Example: (mimikatz.exe_) 5f66b82558ca92e54e77f216ef4c066c:0x473090 + - 0x473090 -> PTR_CreateServiceW_00473090 + - 0x000b34EC -> External Location + """ + locs = [] + for fh in currentProgram.getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 + external_loc = fh.getExternalLocation().getAddress() + if external_loc: + locs.append(external_loc) + return locs + + +def check_addr_for_api( + addr: ghidra.program.model.address.Address, + fakes: Dict[int, List[int]], + imports: Dict[int, List[str]], + externs: Dict[int, List[str]], + ex_locs: List[int], +) -> bool: + offset = addr.getOffset() + + fake = fakes.get(offset) + if fake: + return True + + imp = imports.get(offset) + if imp: + return True + + extern = externs.get(offset) + if extern: + return True + + if addr in ex_locs: + return True + + return False + + +def is_call_or_jmp(insn: ghidra.program.database.code.InstructionDB) -> bool: + return any(mnem in insn.getMnemonicString() for mnem in ["CALL", "J"]) # JMP, JNE, JNZ, etc + + +def is_sp_modified(insn: ghidra.program.database.code.InstructionDB) -> bool: + for i in range(insn.getNumOperands()): + if insn.getOperandType(i) == OperandType.REGISTER: + return "SP" in insn.getRegister(i).getName() and insn.getOperandRefType(i).isWrite() + return False + + +def is_stack_referenced(insn: ghidra.program.database.code.InstructionDB) -> bool: + """generic catch-all for stack references""" + return any(ref.isStackReference() for ref in insn.getReferencesFrom()) + + +def is_zxor(insn: ghidra.program.database.code.InstructionDB) -> bool: + # assume XOR insn + # XOR's against the same operand zero out + ops = [] + operands = [] + for i in range(insn.getNumOperands()): + ops.append(insn.getOpObjects(i)) + + # Operands stored in a 2D array + for j in range(len(ops)): + for k in range(len(ops[j])): + operands.append(ops[j][k]) + + return all(n == operands[0] for n in operands) + + +def dereference_ptr(insn: ghidra.program.database.code.InstructionDB): + to_deref = insn.getAddress(0) + dat = getDataContaining(to_deref) # type: ignore [name-defined] # noqa: F821 + if not dat: + return to_deref + if dat.isDefined() and dat.isPointer(): + addr = dat.getValue() + # now we need to check the addr space to see if it is truly resolvable + # ghidra sometimes likes to hand us direct RAM addrs, which typically point + # to api calls that we can't actually resolve as such + if addr.getAddressSpace().getType() == AddressSpace.TYPE_RAM: + return to_deref + else: + return addr + else: + return to_deref diff --git a/capa/features/extractors/ghidra/insn.py b/capa/features/extractors/ghidra/insn.py new file mode 100644 index 000000000..4002ae281 --- /dev/null +++ b/capa/features/extractors/ghidra/insn.py @@ -0,0 +1,467 @@ +# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: [package root]/LICENSE.txt +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and limitations under the License. +from typing import Any, Dict, Tuple, Iterator + +import ghidra +from ghidra.program.model.lang import OperandType +from ghidra.program.model.block import BasicBlockModel, SimpleBlockModel, SimpleBlockIterator + +import capa.features.extractors.helpers +import capa.features.extractors.ghidra.helpers +from capa.features.insn import API, MAX_STRUCTURE_SIZE, Number, Offset, Mnemonic, OperandNumber, OperandOffset +from capa.features.common import MAX_BYTES_FEATURE_SIZE, Bytes, String, Feature, Characteristic +from capa.features.address import Address, AbsoluteVirtualAddress + +# security cookie checks may perform non-zeroing XORs, these are expected within a certain +# byte range within the first and returning basic blocks, this helps to reduce FP features +SECURITY_COOKIE_BYTES_DELTA = 0x40 + +# significantly cut down on runtime by caching api info +imports = capa.features.extractors.ghidra.helpers.get_file_imports() +externs = capa.features.extractors.ghidra.helpers.get_file_externs() +mapped_fake_addrs = capa.features.extractors.ghidra.helpers.map_fake_import_addrs() +external_locs = capa.features.extractors.ghidra.helpers.get_external_locs() + + +def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: + """check instruction for API call""" + info = () + + # assume only CALLs or JMPs are passed + ref_type = insn.getOperandType(0) + addr_data = OperandType.ADDRESS | OperandType.DATA # needs dereferencing + + if OperandType.isRegister(ref_type): + if OperandType.isAddress(ref_type): + # If it's an address in a register, check the mapped fake addrs + # since they're dereferenced to their fake addrs + op_ref = insn.getAddress(0).getOffset() + ref = mapped_fake_addrs.get(op_ref) # obtain the real addr + if not ref: + return + else: + return + elif ref_type == addr_data: + # we must dereference and check if the addr is a pointer to an api function + addr_ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn) + if addr_ref != insn.getAddress(0): + if not capa.features.extractors.ghidra.helpers.check_addr_for_api( + addr_ref, mapped_fake_addrs, imports, externs, external_locs + ): + return + ref = addr_ref.getOffset() + else: + # could not dereference + return + elif ref_type == OperandType.DYNAMIC | OperandType.ADDRESS or ref_type == OperandType.DYNAMIC: + return # cannot resolve dynamics statically + elif OperandType.isIndirect(ref_type): + return # cannot resolve the indirection statically + else: + # pure address does not need to get dereferenced/ handled + addr_ref = insn.getAddress(0) + if not capa.features.extractors.ghidra.helpers.check_addr_for_api( + addr_ref, mapped_fake_addrs, imports, externs, external_locs + ): + return + ref = addr_ref.getOffset() + + if isinstance(ref, list): # ref from REG | ADDR + for r in ref: + info = funcs.get(r) # type: ignore + if info: + yield info + else: + info = funcs.get(ref) # type: ignore + if info: + yield info + + +def extract_insn_api_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + if not capa.features.extractors.ghidra.helpers.is_call_or_jmp(insn): + return + + # check calls to imported functions + for api in check_for_api_call(insn, imports): + for imp in api: + yield API(imp), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + # check calls to extern functions + for api in check_for_api_call(insn, externs): + for ext in api: + yield API(ext), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def extract_insn_number_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """ + parse instruction number features + example: + push 3136B0h ; dwControlCode + """ + if insn.getMnemonicString().startswith("RET"): + # skip things like: + # .text:0042250E retn 8 + return + + if capa.features.extractors.ghidra.helpers.is_sp_modified(insn): + # skip things like: + # .text:00401145 add esp, 0Ch + return + + for i in range(insn.getNumOperands()): + if insn.getOperandType(i) != OperandType.SCALAR: + # skip things like: + # references, void types + continue + + const = insn.getScalar(i).getValue() + addr = AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + yield Number(const), addr + yield OperandNumber(i, const), addr + + if insn.getMnemonicString().startswith("ADD") and 0 < const < MAX_STRUCTURE_SIZE: + # for pattern like: + # + # add eax, 0x10 + # + # assume 0x10 is also an offset (imagine eax is a pointer). + yield Offset(const), addr + yield OperandOffset(i, const), addr + + +def extract_insn_offset_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """ + parse instruction structure offset features + + example: + .text:0040112F cmp [esi+4], ebx + """ + + # ignore any stack references + if not capa.features.extractors.ghidra.helpers.is_stack_referenced(insn): + # Ghidra stores operands in 2D arrays if they contain offsets + for i in range(insn.getNumOperands()): + if insn.getOperandType(i) == OperandType.DYNAMIC: # e.g. [esi + 4] + # manual extraction, since the default api calls only work on the 1st dimension of the array + op_objs = insn.getOpObjects(i) + if isinstance(op_objs[-1], ghidra.program.model.scalar.Scalar): + op_off = op_objs[-1].getValue() + yield Offset(op_off), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield OperandOffset(i, op_off), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def extract_insn_bytes_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """ + parse referenced byte sequences + example: + push offset iid_004118d4_IShellLinkA ; riid + """ + + if capa.features.extractors.ghidra.helpers.is_call_or_jmp(insn): + return + + ref = insn.getAddress() # init to insn addr + for i in range(insn.getNumOperands()): + if OperandType.isScalarAsAddress(insn.getOperandType(i)): + ref = insn.getAddress(i) # pulls pointer if there is one + + if ref != insn.getAddress(): # bail out if there's no pointer + ghidra_dat = getDataAt(ref) # type: ignore [name-defined] # noqa: F821 + if ( + ghidra_dat and not ghidra_dat.hasStringValue() and not ghidra_dat.isPointer() + ): # avoid if the data itself is a pointer + extracted_bytes = capa.features.extractors.ghidra.helpers.get_bytes(ref, MAX_BYTES_FEATURE_SIZE) + if extracted_bytes and not capa.features.extractors.helpers.all_zeros(extracted_bytes): + # don't extract byte features for obvious strings + yield Bytes(extracted_bytes), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def extract_insn_string_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """ + parse instruction string features + + example: + push offset aAcr ; "ACR > " + """ + ref = insn.getAddress() + for i in range(insn.getNumOperands()): + if OperandType.isScalarAsAddress(insn.getOperandType(i)): + ref = insn.getAddress(i) + + if ref != insn.getAddress(): + ghidra_dat = getDataAt(ref) # type: ignore [name-defined] # noqa: F821 + if ghidra_dat and ghidra_dat.hasStringValue(): + yield String(ghidra_dat.getValue()), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def extract_insn_mnemonic_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """parse instruction mnemonic features""" + yield Mnemonic(insn.getMnemonicString().lower()), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def extract_insn_obfs_call_plus_5_characteristic_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """ + parse call $+5 instruction from the given instruction. + """ + + if not capa.features.extractors.ghidra.helpers.is_call_or_jmp(insn): + return + + code_ref = OperandType.ADDRESS | OperandType.CODE + ref = insn.getAddress() + for i in range(insn.getNumOperands()): + if insn.getOperandType(i) == code_ref: + ref = insn.getAddress(i) + + if insn.getAddress().add(5) == ref: + yield Characteristic("call $+5"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def extract_insn_segment_access_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """parse instruction fs or gs access""" + insn_str = insn.toString() + + if "FS:" in insn_str: + yield Characteristic("fs access"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + if "GS:" in insn_str: + yield Characteristic("gs access"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def extract_insn_peb_access_characteristic_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """parse instruction peb access + + fs:[0x30] on x86, gs:[0x60] on x64 + + """ + insn_str = insn.toString() + if insn_str.startswith(("PUSH", "MOV")): + if "FS:[0x30]" in insn_str or "GS:[0x60]" in insn_str: + yield Characteristic("peb access"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def extract_insn_cross_section_cflow( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """inspect the instruction for a CALL or JMP that crosses section boundaries""" + + if not capa.features.extractors.ghidra.helpers.is_call_or_jmp(insn): + return + + # OperandType to dereference + addr_data = OperandType.ADDRESS | OperandType.DATA + + ref_type = insn.getOperandType(0) + + # both OperandType flags must be present + # bail on REGISTER alone + if OperandType.isRegister(ref_type): + if OperandType.isAddress(ref_type): + ref = insn.getAddress(0) # Ghidra dereferences REG | ADDR + if capa.features.extractors.ghidra.helpers.check_addr_for_api( + ref, mapped_fake_addrs, imports, externs, external_locs + ): + return + else: + return + elif ref_type == addr_data: + # we must dereference and check if the addr is a pointer to an api function + ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn) + if ref != insn.getAddress(0): + if capa.features.extractors.ghidra.helpers.check_addr_for_api( + ref, mapped_fake_addrs, imports, externs, external_locs + ): + return + else: + # could not dereference + return + elif ref_type == OperandType.DYNAMIC | OperandType.ADDRESS or ref_type == OperandType.DYNAMIC: + return # cannot resolve dynamics statically + elif OperandType.isIndirect(ref_type): + return # cannot resolve the indirection statically + else: + # pure address does not need to get dereferenced/ handled + ref = insn.getAddress(0) + if capa.features.extractors.ghidra.helpers.check_addr_for_api( + ref, mapped_fake_addrs, imports, externs, external_locs + ): + return + + this_mem_block = getMemoryBlock(insn.getAddress()) # type: ignore [name-defined] # noqa: F821 + ref_block = getMemoryBlock(ref) # type: ignore [name-defined] # noqa: F821 + if ref_block != this_mem_block: + yield Characteristic("cross section flow"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def extract_function_calls_from( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """extract functions calls from features + + most relevant at the function scope, however, its most efficient to extract at the instruction scope + """ + + if insn.getMnemonicString().startswith("CALL"): + # This method of "dereferencing" addresses/ pointers + # is not as robust as methods in other functions, + # but works just fine for this one + reference = 0 + for ref in insn.getReferencesFrom(): + addr = ref.getToAddress() + + # avoid returning fake addrs + if not addr.isExternalAddress(): + reference = addr.getOffset() + + # if a reference is < 0, then ghidra pulled an offset from a DYNAMIC | ADDR (usually a stackvar) + # these cannot be resolved to actual addrs + if reference > 0: + yield Characteristic("calls from"), AbsoluteVirtualAddress(reference) + + +def extract_function_indirect_call_characteristic_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + """extract indirect function calls (e.g., call eax or call dword ptr [edx+4]) + does not include calls like => call ds:dword_ABD4974 + + most relevant at the function or basic block scope; + however, its most efficient to extract at the instruction scope + """ + if insn.getMnemonicString().startswith("CALL"): + if OperandType.isIndirect(insn.getOperandType(0)): + yield Characteristic("indirect call"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def check_nzxor_security_cookie_delta( + fh: ghidra.program.database.function.FunctionDB, insn: ghidra.program.database.code.InstructionDB +): + """Get the function containing the insn + Get the last block of the function that contains the insn + + Check the bb containing the insn + Check the last bb of the function containing the insn + """ + + model = SimpleBlockModel(currentProgram) # type: ignore [name-defined] # noqa: F821 + insn_addr = insn.getAddress() + func_asv = fh.getBody() + first_addr = func_asv.getMinAddress() + last_addr = func_asv.getMaxAddress() + + if model.getFirstCodeBlockContaining(first_addr, monitor) == model.getFirstCodeBlockContaining(last_addr, monitor): # type: ignore [name-defined] # noqa: F821 + if insn_addr < first_addr.add(SECURITY_COOKIE_BYTES_DELTA): + return True + else: + return insn_addr > last_addr.add(SECURITY_COOKIE_BYTES_DELTA * -1) + else: + return False + + +def extract_insn_nzxor_characteristic_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + if "XOR" not in insn.getMnemonicString(): + return + if capa.features.extractors.ghidra.helpers.is_stack_referenced(insn): + return + if capa.features.extractors.ghidra.helpers.is_zxor(insn): + return + if check_nzxor_security_cookie_delta(fh, insn): + return + yield Characteristic("nzxor"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + + +def extract_features( + fh: ghidra.program.database.function.FunctionDB, + bb: ghidra.program.model.block.CodeBlock, + insn: ghidra.program.database.code.InstructionDB, +) -> Iterator[Tuple[Feature, Address]]: + for insn_handler in INSTRUCTION_HANDLERS: + for feature, addr in insn_handler(fh, bb, insn): + yield feature, addr + + +INSTRUCTION_HANDLERS = ( + extract_insn_api_features, + extract_insn_number_features, + extract_insn_bytes_features, + extract_insn_string_features, + extract_insn_offset_features, + extract_insn_nzxor_characteristic_features, + extract_insn_mnemonic_features, + extract_insn_obfs_call_plus_5_characteristic_features, + extract_insn_peb_access_characteristic_features, + extract_insn_cross_section_cflow, + extract_insn_segment_access_features, + extract_function_calls_from, + extract_function_indirect_call_characteristic_features, +) + + +def main(): + """ """ + listing = currentProgram.getListing() # type: ignore [name-defined] # noqa: F821 + features = [] + for fhandle in capa.features.extractors.ghidra.helpers.get_function_symbols(): + for bab in SimpleBlockIterator(BasicBlockModel(currentProgram), fhandle.getBody(), monitor): # type: ignore [name-defined] # noqa: F821 + for insnh in listing.getInstructions(bab, True): + features.extend(list(extract_features(fhandle, bab, insnh))) + + import pprint + + pprint.pprint(features) # noqa: T203 + + +if __name__ == "__main__": + main() From b3cf1129e3a938482662bfe75fbc66713e5e27b3 Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:58:47 -0700 Subject: [PATCH 23/46] Ghidra: Implement GhidraFeatureExtractor (#1681) * Implement GhidraFeatureExtractor & repo changes --- capa/features/extractors/ghidra/basicblock.py | 31 ++-- capa/features/extractors/ghidra/extractor.py | 43 ++++- capa/features/extractors/ghidra/file.py | 1 + capa/features/extractors/ghidra/function.py | 30 ++-- capa/features/extractors/ghidra/global_.py | 1 + capa/features/extractors/ghidra/helpers.py | 29 +++- capa/features/extractors/ghidra/insn.py | 164 ++++++++---------- capa/ghidra/__init__.py | 0 capa/ghidra/helpers.py | 156 +++++++++++++++++ capa/helpers.py | 2 +- capa/main.py | 44 ++--- rules | 2 +- tests/data | 2 +- 13 files changed, 362 insertions(+), 143 deletions(-) create mode 100644 capa/ghidra/__init__.py create mode 100644 capa/ghidra/helpers.py diff --git a/capa/features/extractors/ghidra/basicblock.py b/capa/features/extractors/ghidra/basicblock.py index ddd241654..f27ad6ed0 100644 --- a/capa/features/extractors/ghidra/basicblock.py +++ b/capa/features/extractors/ghidra/basicblock.py @@ -12,15 +12,16 @@ import ghidra from ghidra.program.model.lang import OperandType -from ghidra.program.model.block import BasicBlockModel, SimpleBlockIterator import capa.features.extractors.ghidra.helpers from capa.features.common import Feature, Characteristic -from capa.features.address import Address, AbsoluteVirtualAddress +from capa.features.address import Address from capa.features.basicblock import BasicBlock from capa.features.extractors.helpers import MIN_STACKSTRING_LEN +from capa.features.extractors.base_extractor import BBHandle, FunctionHandle -listing = currentProgram.getListing() # type: ignore [name-defined] # noqa: F821 +currentProgram = currentProgram() # type: ignore # noqa: F821 +listing = currentProgram.getListing() # type: ignore # noqa: F821 def get_printable_len(op: ghidra.program.model.scalar.Scalar) -> int: @@ -98,16 +99,20 @@ def _bb_has_tight_loop(bb: ghidra.program.model.block.CodeBlock): return False -def extract_bb_stackstring(bb: ghidra.program.model.block.CodeBlock) -> Iterator[Tuple[Feature, Address]]: +def extract_bb_stackstring(fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]: """extract stackstring indicators from basic block""" + bb: ghidra.program.model.block.CodeBlock = bbh.inner + if bb_contains_stackstring(bb): - yield Characteristic("stack string"), AbsoluteVirtualAddress(bb.getMinAddress().getOffset()) + yield Characteristic("stack string"), bbh.address -def extract_bb_tight_loop(bb: ghidra.program.model.block.CodeBlock) -> Iterator[Tuple[Feature, Address]]: +def extract_bb_tight_loop(fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]: """check basic block for tight loop indicators""" + bb: ghidra.program.model.block.CodeBlock = bbh.inner + if _bb_has_tight_loop(bb): - yield Characteristic("tight loop"), AbsoluteVirtualAddress(bb.getMinAddress().getOffset()) + yield Characteristic("tight loop"), bbh.address BASIC_BLOCK_HANDLERS = ( @@ -116,7 +121,7 @@ def extract_bb_tight_loop(bb: ghidra.program.model.block.CodeBlock) -> Iterator[ ) -def extract_features(bb: ghidra.program.model.block.CodeBlock) -> Iterator[Tuple[Feature, Address]]: +def extract_features(fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]: """ extract features from the given basic block. @@ -126,17 +131,17 @@ def extract_features(bb: ghidra.program.model.block.CodeBlock) -> Iterator[Tuple yields: Tuple[Feature, int]: the features and their location found in this basic block. """ - yield BasicBlock(), AbsoluteVirtualAddress(bb.getMinAddress().getOffset()) + yield BasicBlock(), bbh.address for bb_handler in BASIC_BLOCK_HANDLERS: - for feature, addr in bb_handler(bb): + for feature, addr in bb_handler(fh, bbh): yield feature, addr def main(): features = [] - for fhandle in capa.features.extractors.ghidra.helpers.get_function_symbols(): - for bb in SimpleBlockIterator(BasicBlockModel(currentProgram), fhandle.getBody(), monitor): # type: ignore [name-defined] # noqa: F821 - features.extend(list(extract_features(bb))) + for fh in capa.features.extractors.ghidra.helpers.get_function_symbols(): + for bbh in capa.features.extractors.ghidra.helpers.get_function_blocks(fh): + features.extend(list(extract_features(fh, bbh))) import pprint diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py index af5047374..83a6716a5 100644 --- a/capa/features/extractors/ghidra/extractor.py +++ b/capa/features/extractors/ghidra/extractor.py @@ -5,16 +5,19 @@ # Unless required by applicable law or agreed to in writing, software distributed under the License # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and limitations under the License. -from typing import List, Tuple - -import ghidra +from typing import List, Tuple, Iterator +import capa.features.extractors.ghidra.file +import capa.features.extractors.ghidra.insn import capa.features.extractors.ghidra.global_ +import capa.features.extractors.ghidra.function +import capa.features.extractors.ghidra.basicblock from capa.features.common import Feature from capa.features.address import Address, AbsoluteVirtualAddress -from capa.features.extractors.base_extractor import FeatureExtractor +from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle, FeatureExtractor -currentProgram: ghidra.program.database.ProgramDB +currentProgram = currentProgram() # type: ignore # noqa: F821 +currentAddress = currentAddress() # type: ignore # noqa: F821 class GhidraFeatureExtractor(FeatureExtractor): @@ -33,3 +36,33 @@ def extract_global_features(self): def extract_file_features(self): yield from capa.features.extractors.ghidra.file.extract_features() + + def get_functions(self) -> Iterator[FunctionHandle]: + import capa.features.extractors.ghidra.helpers as ghidra_helpers + + yield from ghidra_helpers.get_function_symbols() + + @staticmethod + def get_function(addr: int) -> FunctionHandle: + get_addr = currentAddress.getAddress(hex(addr)) # type: ignore [name-defined] # noqa: F821 + func = getFunctionContaining(get_addr) # type: ignore [name-defined] # noqa: F821 + return FunctionHandle(address=AbsoluteVirtualAddress(func.getAddress().getOffset()), inner=func) + + def extract_function_features(self, fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]: + yield from capa.features.extractors.ghidra.function.extract_features(fh) + + def get_basic_blocks(self, fh: FunctionHandle) -> Iterator[BBHandle]: + import capa.features.extractors.ghidra.helpers as ghidra_helpers + + yield from ghidra_helpers.get_function_blocks(fh) + + def extract_basic_block_features(self, fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]: + yield from capa.features.extractors.ghidra.basicblock.extract_features(fh, bbh) + + def get_instructions(self, fh: FunctionHandle, bbh: BBHandle) -> Iterator[InsnHandle]: + import capa.features.extractors.ghidra.helpers as ghidra_helpers + + yield from ghidra_helpers.get_insn_in_range(bbh) + + def extract_insn_features(self, fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle): + yield from capa.features.extractors.ghidra.insn.extract_features(fh, bbh, ih) diff --git a/capa/features/extractors/ghidra/file.py b/capa/features/extractors/ghidra/file.py index 8845354f1..f3da41f9d 100644 --- a/capa/features/extractors/ghidra/file.py +++ b/capa/features/extractors/ghidra/file.py @@ -19,6 +19,7 @@ from capa.features.common import FORMAT_PE, FORMAT_ELF, Format, String, Feature, Characteristic from capa.features.address import NO_ADDRESS, Address, FileOffsetAddress, AbsoluteVirtualAddress +currentProgram = currentProgram() # type: ignore # noqa: F821 MAX_OFFSET_PE_AFTER_MZ = 0x200 diff --git a/capa/features/extractors/ghidra/function.py b/capa/features/extractors/ghidra/function.py index 98d4ee9ba..3f9c956ce 100644 --- a/capa/features/extractors/ghidra/function.py +++ b/capa/features/extractors/ghidra/function.py @@ -14,19 +14,25 @@ from capa.features.common import Feature, Characteristic from capa.features.address import Address, AbsoluteVirtualAddress from capa.features.extractors import loops +from capa.features.extractors.base_extractor import FunctionHandle +currentProgram = currentProgram() # type: ignore # noqa: F821 +monitor = monitor() # type: ignore # noqa: F821 -def extract_function_calls_to(fh: ghidra.program.database.function.FunctionDB): + +def extract_function_calls_to(fh: FunctionHandle): """extract callers to a function""" - for ref in fh.getSymbol().getReferences(): + f: ghidra.program.database.function.FunctionDB = fh.inner + for ref in f.getSymbol().getReferences(): if ref.getReferenceType().isCall(): yield Characteristic("calls to"), AbsoluteVirtualAddress(ref.getFromAddress().getOffset()) -def extract_function_loop(fh: ghidra.program.database.function.FunctionDB): - edges = [] +def extract_function_loop(fh: FunctionHandle): + f: ghidra.program.database.function.FunctionDB = fh.inner - for block in SimpleBlockIterator(BasicBlockModel(currentProgram), fh.getBody(), monitor): # type: ignore [name-defined] # noqa: F821 + edges = [] + for block in SimpleBlockIterator(BasicBlockModel(currentProgram), f.getBody(), monitor): # type: ignore [name-defined] # noqa: F821 dests = block.getDestinations(monitor) # type: ignore [name-defined] # noqa: F821 s_addrs = block.getStartAddresses() @@ -35,16 +41,18 @@ def extract_function_loop(fh: ghidra.program.database.function.FunctionDB): edges.append((addr.getOffset(), dests.next().getDestinationAddress().getOffset())) if loops.has_loop(edges): - yield Characteristic("loop"), AbsoluteVirtualAddress(fh.getEntryPoint().getOffset()) + yield Characteristic("loop"), AbsoluteVirtualAddress(f.getEntryPoint().getOffset()) + +def extract_recursive_call(fh: FunctionHandle): + f: ghidra.program.database.function.FunctionDB = fh.inner -def extract_recursive_call(fh: ghidra.program.database.function.FunctionDB): - for f in fh.getCalledFunctions(monitor): # type: ignore [name-defined] # noqa: F821 - if f.getEntryPoint().getOffset() == fh.getEntryPoint().getOffset(): - yield Characteristic("recursive call"), AbsoluteVirtualAddress(fh.getEntryPoint().getOffset()) + for func in f.getCalledFunctions(monitor): # type: ignore [name-defined] # noqa: F821 + if func.getEntryPoint().getOffset() == f.getEntryPoint().getOffset(): + yield Characteristic("recursive call"), AbsoluteVirtualAddress(f.getEntryPoint().getOffset()) -def extract_features(fh: ghidra.program.database.function.FunctionDB) -> Iterator[Tuple[Feature, Address]]: +def extract_features(fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]: for func_handler in FUNCTION_HANDLERS: for feature, addr in func_handler(fh): yield feature, addr diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py index bf78baece..59797dec9 100644 --- a/capa/features/extractors/ghidra/global_.py +++ b/capa/features/extractors/ghidra/global_.py @@ -15,6 +15,7 @@ from capa.features.address import NO_ADDRESS, Address logger = logging.getLogger(__name__) +currentProgram = currentProgram() # type: ignore # noqa: F821 def extract_os() -> Iterator[Tuple[Feature, Address]]: diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py index 5bf6b9a8d..6f520b09e 100644 --- a/capa/features/extractors/ghidra/helpers.py +++ b/capa/features/extractors/ghidra/helpers.py @@ -9,10 +9,16 @@ import ghidra from ghidra.program.model.lang import OperandType +from ghidra.program.model.block import BasicBlockModel, SimpleBlockIterator from ghidra.program.model.symbol import SourceType, SymbolType from ghidra.program.model.address import AddressSpace import capa.features.extractors.helpers +from capa.features.address import AbsoluteVirtualAddress +from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle + +monitor = monitor() # type: ignore # noqa: F821 +currentProgram = currentProgram() # type: ignore # noqa: F821 def fix_byte(b: int) -> bytes: @@ -71,10 +77,29 @@ def get_block_bytes(block: ghidra.program.model.mem.MemoryBlock) -> bytes: return bytez -def get_function_symbols() -> Iterator[ghidra.program.database.function.FunctionDB]: +def get_function_symbols() -> Iterator[FunctionHandle]: """yield all non-external function symbols""" - yield from currentProgram.getFunctionManager().getFunctionsNoStubs(True) # type: ignore [name-defined] # noqa: F821 + for fhandle in currentProgram.getFunctionManager().getFunctionsNoStubs(True): # type: ignore [name-defined] # noqa: F821 + yield FunctionHandle(address=AbsoluteVirtualAddress(fhandle.getEntryPoint().getOffset()), inner=fhandle) + + +def get_function_blocks(fh: FunctionHandle) -> Iterator[BBHandle]: + """yield BBHandle for each bb in a given function""" + + func: ghidra.program.database.function.FunctionDB = fh.inner + for bb in SimpleBlockIterator(BasicBlockModel(currentProgram), func.getBody(), monitor): # type: ignore [name-defined] # noqa: F821 + yield BBHandle(address=AbsoluteVirtualAddress(bb.getMinAddress().getOffset()), inner=bb) + + +def get_insn_in_range(bbh: BBHandle) -> Iterator[InsnHandle]: + """yield InshHandle for each insn in a given basicblock""" + + bb: ghidra.program.model.block.CodeBlock = bbh.inner + for addr in bb.getAddresses(True): + insn = getInstructionAt(addr) # type: ignore [name-defined] # noqa: F821 + if insn: + yield InsnHandle(address=AbsoluteVirtualAddress(insn.getAddress().getOffset()), inner=insn) def get_file_imports() -> Dict[int, List[str]]: diff --git a/capa/features/extractors/ghidra/insn.py b/capa/features/extractors/ghidra/insn.py index 4002ae281..9c77286f8 100644 --- a/capa/features/extractors/ghidra/insn.py +++ b/capa/features/extractors/ghidra/insn.py @@ -9,17 +9,20 @@ import ghidra from ghidra.program.model.lang import OperandType -from ghidra.program.model.block import BasicBlockModel, SimpleBlockModel, SimpleBlockIterator +from ghidra.program.model.block import SimpleBlockModel import capa.features.extractors.helpers import capa.features.extractors.ghidra.helpers from capa.features.insn import API, MAX_STRUCTURE_SIZE, Number, Offset, Mnemonic, OperandNumber, OperandOffset from capa.features.common import MAX_BYTES_FEATURE_SIZE, Bytes, String, Feature, Characteristic from capa.features.address import Address, AbsoluteVirtualAddress +from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle # security cookie checks may perform non-zeroing XORs, these are expected within a certain # byte range within the first and returning basic blocks, this helps to reduce FP features SECURITY_COOKIE_BYTES_DELTA = 0x40 +currentProgram = currentProgram() # type: ignore # noqa: F821 +monitor = monitor() # type: ignore # noqa: F821 # significantly cut down on runtime by caching api info imports = capa.features.extractors.ghidra.helpers.get_file_imports() @@ -49,15 +52,11 @@ def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: elif ref_type == addr_data: # we must dereference and check if the addr is a pointer to an api function addr_ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn) - if addr_ref != insn.getAddress(0): - if not capa.features.extractors.ghidra.helpers.check_addr_for_api( - addr_ref, mapped_fake_addrs, imports, externs, external_locs - ): - return - ref = addr_ref.getOffset() - else: - # could not dereference + if not capa.features.extractors.ghidra.helpers.check_addr_for_api( + addr_ref, mapped_fake_addrs, imports, externs, external_locs + ): return + ref = addr_ref.getOffset() elif ref_type == OperandType.DYNAMIC | OperandType.ADDRESS or ref_type == OperandType.DYNAMIC: return # cannot resolve dynamics statically elif OperandType.isIndirect(ref_type): @@ -82,35 +81,31 @@ def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: yield info -def extract_insn_api_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, -) -> Iterator[Tuple[Feature, Address]]: +def extract_insn_api_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]: + insn: ghidra.program.database.code.InstructionDB = ih.inner + if not capa.features.extractors.ghidra.helpers.is_call_or_jmp(insn): return # check calls to imported functions for api in check_for_api_call(insn, imports): for imp in api: - yield API(imp), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield API(imp), ih.address # check calls to extern functions for api in check_for_api_call(insn, externs): for ext in api: - yield API(ext), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield API(ext), ih.address -def extract_insn_number_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, -) -> Iterator[Tuple[Feature, Address]]: +def extract_insn_number_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]: """ parse instruction number features example: push 3136B0h ; dwControlCode """ + insn: ghidra.program.database.code.InstructionDB = ih.inner + if insn.getMnemonicString().startswith("RET"): # skip things like: # .text:0042250E retn 8 @@ -128,7 +123,7 @@ def extract_insn_number_features( continue const = insn.getScalar(i).getValue() - addr = AbsoluteVirtualAddress(insn.getAddress().getOffset()) + addr = ih.address yield Number(const), addr yield OperandNumber(i, const), addr @@ -143,17 +138,14 @@ def extract_insn_number_features( yield OperandOffset(i, const), addr -def extract_insn_offset_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, -) -> Iterator[Tuple[Feature, Address]]: +def extract_insn_offset_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]: """ parse instruction structure offset features example: .text:0040112F cmp [esi+4], ebx """ + insn: ghidra.program.database.code.InstructionDB = ih.inner # ignore any stack references if not capa.features.extractors.ghidra.helpers.is_stack_referenced(insn): @@ -164,20 +156,17 @@ def extract_insn_offset_features( op_objs = insn.getOpObjects(i) if isinstance(op_objs[-1], ghidra.program.model.scalar.Scalar): op_off = op_objs[-1].getValue() - yield Offset(op_off), AbsoluteVirtualAddress(insn.getAddress().getOffset()) - yield OperandOffset(i, op_off), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield Offset(op_off), ih.address + yield OperandOffset(i, op_off), ih.address -def extract_insn_bytes_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, -) -> Iterator[Tuple[Feature, Address]]: +def extract_insn_bytes_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]: """ parse referenced byte sequences example: push offset iid_004118d4_IShellLinkA ; riid """ + insn: ghidra.program.database.code.InstructionDB = ih.inner if capa.features.extractors.ghidra.helpers.is_call_or_jmp(insn): return @@ -195,20 +184,18 @@ def extract_insn_bytes_features( extracted_bytes = capa.features.extractors.ghidra.helpers.get_bytes(ref, MAX_BYTES_FEATURE_SIZE) if extracted_bytes and not capa.features.extractors.helpers.all_zeros(extracted_bytes): # don't extract byte features for obvious strings - yield Bytes(extracted_bytes), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield Bytes(extracted_bytes), ih.address -def extract_insn_string_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, -) -> Iterator[Tuple[Feature, Address]]: +def extract_insn_string_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]: """ parse instruction string features example: push offset aAcr ; "ACR > " """ + insn: ghidra.program.database.code.InstructionDB = ih.inner + ref = insn.getAddress() for i in range(insn.getNumOperands()): if OperandType.isScalarAsAddress(insn.getOperandType(i)): @@ -217,26 +204,25 @@ def extract_insn_string_features( if ref != insn.getAddress(): ghidra_dat = getDataAt(ref) # type: ignore [name-defined] # noqa: F821 if ghidra_dat and ghidra_dat.hasStringValue(): - yield String(ghidra_dat.getValue()), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield String(ghidra_dat.getValue()), ih.address def extract_insn_mnemonic_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, + fh: FunctionHandle, bb: BBHandle, ih: InsnHandle ) -> Iterator[Tuple[Feature, Address]]: """parse instruction mnemonic features""" - yield Mnemonic(insn.getMnemonicString().lower()), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + insn: ghidra.program.database.code.InstructionDB = ih.inner + + yield Mnemonic(insn.getMnemonicString().lower()), ih.address def extract_insn_obfs_call_plus_5_characteristic_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, + fh: FunctionHandle, bb: BBHandle, ih: InsnHandle ) -> Iterator[Tuple[Feature, Address]]: """ parse call $+5 instruction from the given instruction. """ + insn: ghidra.program.database.code.InstructionDB = ih.inner if not capa.features.extractors.ghidra.helpers.is_call_or_jmp(insn): return @@ -248,46 +234,45 @@ def extract_insn_obfs_call_plus_5_characteristic_features( ref = insn.getAddress(i) if insn.getAddress().add(5) == ref: - yield Characteristic("call $+5"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield Characteristic("call $+5"), ih.address def extract_insn_segment_access_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, + fh: FunctionHandle, bb: BBHandle, ih: InsnHandle ) -> Iterator[Tuple[Feature, Address]]: """parse instruction fs or gs access""" + insn: ghidra.program.database.code.InstructionDB = ih.inner + insn_str = insn.toString() if "FS:" in insn_str: - yield Characteristic("fs access"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield Characteristic("fs access"), ih.address if "GS:" in insn_str: - yield Characteristic("gs access"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield Characteristic("gs access"), ih.address def extract_insn_peb_access_characteristic_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, + fh: FunctionHandle, bb: BBHandle, ih: InsnHandle ) -> Iterator[Tuple[Feature, Address]]: """parse instruction peb access fs:[0x30] on x86, gs:[0x60] on x64 """ + insn: ghidra.program.database.code.InstructionDB = ih.inner + insn_str = insn.toString() if insn_str.startswith(("PUSH", "MOV")): if "FS:[0x30]" in insn_str or "GS:[0x60]" in insn_str: - yield Characteristic("peb access"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield Characteristic("peb access"), ih.address def extract_insn_cross_section_cflow( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, + fh: FunctionHandle, bb: BBHandle, ih: InsnHandle ) -> Iterator[Tuple[Feature, Address]]: """inspect the instruction for a CALL or JMP that crosses section boundaries""" + insn: ghidra.program.database.code.InstructionDB = ih.inner if not capa.features.extractors.ghidra.helpers.is_call_or_jmp(insn): return @@ -311,13 +296,9 @@ def extract_insn_cross_section_cflow( elif ref_type == addr_data: # we must dereference and check if the addr is a pointer to an api function ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn) - if ref != insn.getAddress(0): - if capa.features.extractors.ghidra.helpers.check_addr_for_api( - ref, mapped_fake_addrs, imports, externs, external_locs - ): - return - else: - # could not dereference + if capa.features.extractors.ghidra.helpers.check_addr_for_api( + ref, mapped_fake_addrs, imports, externs, external_locs + ): return elif ref_type == OperandType.DYNAMIC | OperandType.ADDRESS or ref_type == OperandType.DYNAMIC: return # cannot resolve dynamics statically @@ -334,18 +315,19 @@ def extract_insn_cross_section_cflow( this_mem_block = getMemoryBlock(insn.getAddress()) # type: ignore [name-defined] # noqa: F821 ref_block = getMemoryBlock(ref) # type: ignore [name-defined] # noqa: F821 if ref_block != this_mem_block: - yield Characteristic("cross section flow"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield Characteristic("cross section flow"), ih.address def extract_function_calls_from( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, + fh: FunctionHandle, + bb: BBHandle, + ih: InsnHandle, ) -> Iterator[Tuple[Feature, Address]]: """extract functions calls from features most relevant at the function scope, however, its most efficient to extract at the instruction scope """ + insn: ghidra.program.database.code.InstructionDB = ih.inner if insn.getMnemonicString().startswith("CALL"): # This method of "dereferencing" addresses/ pointers @@ -366,9 +348,9 @@ def extract_function_calls_from( def extract_function_indirect_call_characteristic_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, + fh: FunctionHandle, + bb: BBHandle, + ih: InsnHandle, ) -> Iterator[Tuple[Feature, Address]]: """extract indirect function calls (e.g., call eax or call dword ptr [edx+4]) does not include calls like => call ds:dword_ABD4974 @@ -376,9 +358,11 @@ def extract_function_indirect_call_characteristic_features( most relevant at the function or basic block scope; however, its most efficient to extract at the instruction scope """ + insn: ghidra.program.database.code.InstructionDB = ih.inner + if insn.getMnemonicString().startswith("CALL"): if OperandType.isIndirect(insn.getOperandType(0)): - yield Characteristic("indirect call"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield Characteristic("indirect call"), ih.address def check_nzxor_security_cookie_delta( @@ -407,25 +391,28 @@ def check_nzxor_security_cookie_delta( def extract_insn_nzxor_characteristic_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, + fh: FunctionHandle, + bb: BBHandle, + ih: InsnHandle, ) -> Iterator[Tuple[Feature, Address]]: + f: ghidra.program.database.function.FunctionDB = fh.inner + insn: ghidra.program.database.code.InstructionDB = ih.inner + if "XOR" not in insn.getMnemonicString(): return if capa.features.extractors.ghidra.helpers.is_stack_referenced(insn): return if capa.features.extractors.ghidra.helpers.is_zxor(insn): return - if check_nzxor_security_cookie_delta(fh, insn): + if check_nzxor_security_cookie_delta(f, insn): return - yield Characteristic("nzxor"), AbsoluteVirtualAddress(insn.getAddress().getOffset()) + yield Characteristic("nzxor"), ih.address def extract_features( - fh: ghidra.program.database.function.FunctionDB, - bb: ghidra.program.model.block.CodeBlock, - insn: ghidra.program.database.code.InstructionDB, + fh: FunctionHandle, + bb: BBHandle, + insn: InsnHandle, ) -> Iterator[Tuple[Feature, Address]]: for insn_handler in INSTRUCTION_HANDLERS: for feature, addr in insn_handler(fh, bb, insn): @@ -451,12 +438,11 @@ def extract_features( def main(): """ """ - listing = currentProgram.getListing() # type: ignore [name-defined] # noqa: F821 features = [] - for fhandle in capa.features.extractors.ghidra.helpers.get_function_symbols(): - for bab in SimpleBlockIterator(BasicBlockModel(currentProgram), fhandle.getBody(), monitor): # type: ignore [name-defined] # noqa: F821 - for insnh in listing.getInstructions(bab, True): - features.extend(list(extract_features(fhandle, bab, insnh))) + for fh in capa.features.extractors.ghidra.helpers.get_function_symbols(): + for bb in capa.features.extractors.ghidra.helpers.get_function_blocks(fh): + for insn in capa.features.extractors.ghidra.helpers.get_insn_in_range(bb): + features.extend(list(extract_features(fh, bb, insn))) import pprint diff --git a/capa/ghidra/__init__.py b/capa/ghidra/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/capa/ghidra/helpers.py b/capa/ghidra/helpers.py new file mode 100644 index 000000000..ffe0d3738 --- /dev/null +++ b/capa/ghidra/helpers.py @@ -0,0 +1,156 @@ +# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: [package root]/LICENSE.txt +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and limitations under the License. +import logging +import datetime +import contextlib +from typing import List +from pathlib import Path + +import capa +import capa.version +import capa.features.common +import capa.features.freeze +import capa.render.result_document as rdoc +import capa.features.extractors.ghidra.helpers + +logger = logging.getLogger("capa") + +currentProgram = currentProgram() # type: ignore # noqa: F821 +currentAddress = currentAddress() # type: ignore # noqa: F821 + +# file type as returned by Ghidra +SUPPORTED_FILE_TYPES = ("Executable and Linking Format (ELF)", "Portable Executable (PE)", "Raw Binary") + + +class GHIDRAIO: + """ + An object that acts as a file-like object, + using bytes from the current Ghidra listing. + """ + + def __init__(self): + super().__init__() + self.offset = 0 + + def seek(self, offset, whence=0): + assert whence == 0 + self.offset = offset + + def read(self, size): + try: + # ghidra.program.model.address.Address has no public constructor, + # so we have to use the exposed currentAddress object for its + # member function .getAddress() + ea = currentAddress.getAddress(hex(self.offset)) # type: ignore [name-defined] # noqa: F821 + except RuntimeError: # AddressFormatException to Ghidra + logger.debug("cannot read 0x%x bytes at 0x%x (ea: BADADDR)", size, self.offset) + return b"" + + logger.debug("reading 0x%x bytes at 0x%x (ea: 0x%x)", size, self.offset, ea.getOffset()) + + # returns bytes or b"" + return capa.features.extractors.ghidra.helpers.get_bytes(ea, size) + + def close(self): + return + + +def is_supported_ghidra_version(): + version = float(getGhidraVersion()[:4]) # type: ignore [name-defined] # noqa: F821 + if version < 10.2: + warning_msg = "capa does not support this Ghidra version" + logger.warning(warning_msg) + logger.warning("Your Ghidra version is: %s. Supported versions are: Ghidra >= 10.2", version) + return False + return True + + +def is_running_headless(): + return isRunningHeadless() # type: ignore [name-defined] # noqa: F821 + + +def is_supported_file_type(): + file_info = currentProgram.getExecutableFormat() # type: ignore [name-defined] # noqa: F821 + if file_info.filetype not in SUPPORTED_FILE_TYPES: + logger.error("-" * 80) + logger.error(" Input file does not appear to be a supported file type.") + logger.error(" ") + logger.error( + " capa currently only supports analyzing PE, ELF, or binary files containing x86 (32- and 64-bit) shellcode." + ) + logger.error(" If you don't know the input file type, you can try using the `file` utility to guess it.") + logger.error("-" * 80) + return False + return True + + +def is_supported_arch_type(): + file_info = currentProgram.getLanguageID() # type: ignore [name-defined] # noqa: F821 + if "x86" not in file_info or not any(arch in file_info for arch in ["32", "64"]): + logger.error("-" * 80) + logger.error(" Input file does not appear to target a supported architecture.") + logger.error(" ") + logger.error(" capa currently only supports analyzing x86 (32- and 64-bit).") + logger.error("-" * 80) + return False + return True + + +def get_file_md5(): + return currentProgram.getExecutableMD5() # type: ignore [name-defined] # noqa: F821 + + +def get_file_sha256(): + return currentProgram.getExecutableSHA256() # type: ignore [name-defined] # noqa: F821 + + +def collect_metadata(rules: List[Path]): + md5 = get_file_md5() + sha256 = get_file_sha256() + + info = currentProgram.getLanguageID().toString() # type: ignore [name-defined] # noqa: F821 + if "x86" in info and "64" in info: + arch = "x86_64" + elif "x86" in info and "32" in info: + arch = "x86" + else: + arch = "unknown arch" + + format_name: str = currentProgram.getExecutableFormat() # type: ignore [name-defined] # noqa: F821 + if "PE" in format_name: + os = "windows" + elif "ELF" in format_name: + with contextlib.closing(capa.ghidra.helpers.GHIDRAIO()) as f: + os = capa.features.extractors.elf.detect_elf_os(f) + else: + os = "unknown os" + + return rdoc.Metadata( + timestamp=datetime.datetime.now(), + version=capa.version.__version__, + argv=(), + sample=rdoc.Sample( + md5=md5, + sha1="", + sha256=sha256, + path=currentProgram.getExecutablePath(), # type: ignore [name-defined] # noqa: F821 + ), + analysis=rdoc.Analysis( + format=currentProgram.getExecutableFormat(), # type: ignore [name-defined] # noqa: F821 + arch=arch, + os=os, + extractor="ghidra", + rules=tuple(r.resolve().absolute().as_posix() for r in rules), + base_address=capa.features.freeze.Address.from_capa(currentProgram.getImageBase().getOffset()), # type: ignore [name-defined] # noqa: F821 + layout=rdoc.Layout( + functions=(), + ), + feature_counts=rdoc.FeatureCounts(file=0, functions=()), + library_functions=(), + ), + ) diff --git a/capa/helpers.py b/capa/helpers.py index 69c7ccf2a..c1d2ebf5e 100644 --- a/capa/helpers.py +++ b/capa/helpers.py @@ -44,7 +44,7 @@ def is_runtime_ida(): def is_runtime_ghidra(): - return importlib.util.find_spec("ghidra.program.flatapi") is not None + return importlib.util.find_spec("ghidra") is not None def assert_never(value) -> NoReturn: diff --git a/capa/main.py b/capa/main.py index 07bb007d0..8839f8899 100644 --- a/capa/main.py +++ b/capa/main.py @@ -256,6 +256,11 @@ def find_capabilities(ruleset: RuleSet, extractor: FeatureExtractor, disable_pro with redirecting_print_to_tqdm(disable_progress): with tqdm.contrib.logging.logging_redirect_tqdm(): pbar = tqdm.tqdm + if capa.helpers.is_runtime_ghidra(): + # Ghidrathon interpreter cannot properly handle + # the TMonitor thread that is created via a monitor_interval + # > 0 + pbar.monitor_interval = 0 if disable_progress: # do not use tqdm to avoid unnecessary side effects when caller intends # to disable progress completely @@ -1340,14 +1345,9 @@ def ida_main(): def ghidra_main(): import capa.rules - import capa.features.extractors.ghidra.file - - # import capa.render.default - # import capa.features.extractors.ghidra.extractor - import capa.features.extractors.ghidra.global_ - import capa.features.extractors.ghidra.helpers - import capa.features.extractors.ghidra.function - from capa.features.common import Feature + import capa.ghidra.helpers + import capa.render.default + import capa.features.extractors.ghidra.extractor logging.basicConfig(level=logging.INFO) logging.getLogger().setLevel(logging.INFO) @@ -1359,21 +1359,25 @@ def ghidra_main(): logger.debug(" https://github.com/mandiant/capa-rules") logger.debug("-" * 80) - # rules_path = os.path.join(get_default_root(), "rules") - # logger.debug("rule path: %s", rules_path) - # rules = get_rules([rules_path]) + rules_path = get_default_root() / "rules" + logger.debug("rule path: %s", rules_path) + rules = get_rules([rules_path]) + + meta = capa.ghidra.helpers.collect_metadata([rules_path]) - # temp test for ghidra CI - ghidra_features: List[Tuple[Feature, Address]] = [] - ghidra_features.extend(capa.features.extractors.ghidra.global_.extract_os()) - ghidra_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) - ghidra_features.extend(capa.features.extractors.ghidra.file.extract_features()) - for fhandle in capa.features.extractors.ghidra.helpers.get_function_symbols(): - ghidra_features.extend(list(capa.features.extractors.ghidra.function.extract_features(fhandle))) + capabilities, counts = find_capabilities( + rules, + capa.features.extractors.ghidra.extractor.GhidraFeatureExtractor(), + not capa.ghidra.helpers.is_running_headless(), + ) + + meta.analysis.feature_counts = counts["feature_counts"] + meta.analysis.library_functions = counts["library_functions"] - import pprint + if has_file_limitation(rules, capabilities, is_standalone=False): + logger.info("capa encountered warnings during analysis") - pprint.pprint(ghidra_features) # noqa: T203 + print(capa.render.default.render(meta, rules, capabilities)) if __name__ == "__main__": diff --git a/rules b/rules index 149cf2d13..7685a232d 160000 --- a/rules +++ b/rules @@ -1 +1 @@ -Subproject commit 149cf2d133a0ea08b4eb250388e9f93c67b83cbf +Subproject commit 7685a232d94acbe7e69addb8bd89d752c9fa27a2 diff --git a/tests/data b/tests/data index cf965117c..faf741a53 160000 --- a/tests/data +++ b/tests/data @@ -1 +1 @@ -Subproject commit cf965117cbb3d7391bf01ab8dfb049262a3ad4fd +Subproject commit faf741a538224f52d4412468f910d52a70911662 From 058c1fefd2ddb9e2c01d16b104c1848729c8353b Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Mon, 21 Aug 2023 11:16:13 -0700 Subject: [PATCH 24/46] ghidra: unit tests (#1727) * restore from corrupted .git * lint repo * temp: remove lint failing rule * implement dereferencing, clean up extractors * implement proper dereferencing routines as applicable * fix nzxor implementation, remediate ghidra analysis issues * lint repo * Assert typing, lint repo * avoid extracting pointers in bytes extraction * attempt to recover submodule * implement GhidraFeatureExtractor & ghidra_main() * lint repo * document examples, clean-up & testing * lint repo * properly map import dict * properly map fake addresses * fix fake addr mapping * properly map externs * re-align consistency with other backends * lint repo * fix dereferencing routine * clean up helpers * fix format string * disable progress bar to exit gracefully * enable pbar in headless runtime mode * implement fixture test script * implement ghidra unit test script * refactor repo for breaking Ghidrathon change * bump ghidrathon CI version, run unit test in CI * change CI config * fix wget line for ghidrathon * fix unzip paths * fix ghidra import issue * disable pytest faulthandler module * fix ghidra state variables * use toAddr * restructure for consistency * Bump Ghidrathon version for CI, fix pytest ghidra runtime detection --- .github/workflows/tests.yml | 6 +- capa/features/extractors/ghidra/basicblock.py | 8 +- capa/features/extractors/ghidra/extractor.py | 8 +- capa/features/extractors/ghidra/file.py | 15 ++-- capa/features/extractors/ghidra/function.py | 9 +- capa/features/extractors/ghidra/global_.py | 7 +- capa/features/extractors/ghidra/helpers.py | 17 ++-- capa/features/extractors/ghidra/insn.py | 10 ++- tests/fixtures.py | 12 ++- tests/test_ghidra_features.py | 89 +++++++++++++++++++ 10 files changed, 133 insertions(+), 48 deletions(-) create mode 100644 tests/test_ghidra_features.py diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e5265340c..6b0f7dd0f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -153,7 +153,7 @@ jobs: ghidra-version: ["10.3"] public-version: ["PUBLIC_20230510"] # for ghidra releases jep-version: ["4.1.1"] - ghidrathon-version: ["2.1.0"] + ghidrathon-version: ["3.0.0"] steps: - name: Checkout capa with submodules uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 @@ -194,7 +194,5 @@ jobs: - name: Install capa run: pip install -e .[dev] - name: Run tests - run: | # runs main.py for now... - .github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC/support/analyzeHeadless .github/ghidra/project ghidra_test -Import ./tests/data/'Practical Malware Analysis Lab 01-01.dll_' - .github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC/support/analyzeHeadless .github/ghidra/project ghidra_test -process 'Practical Malware Analysis Lab 01-01.dll_' -ScriptPath ./capa -PostScript main.py + run: .github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC/support/analyzeHeadless .github/ghidra/project ghidra_test -Import ./tests/data/'mimikatz.exe_' -ScriptPath ./tests/ -PostScript test_ghidra_features.py diff --git a/capa/features/extractors/ghidra/basicblock.py b/capa/features/extractors/ghidra/basicblock.py index f27ad6ed0..7811ba0c3 100644 --- a/capa/features/extractors/ghidra/basicblock.py +++ b/capa/features/extractors/ghidra/basicblock.py @@ -20,9 +20,6 @@ from capa.features.extractors.helpers import MIN_STACKSTRING_LEN from capa.features.extractors.base_extractor import BBHandle, FunctionHandle -currentProgram = currentProgram() # type: ignore # noqa: F821 -listing = currentProgram.getListing() # type: ignore # noqa: F821 - def get_printable_len(op: ghidra.program.model.scalar.Scalar) -> int: """Return string length if all operand bytes are ascii or utf16-le printable""" @@ -79,7 +76,7 @@ def bb_contains_stackstring(bb: ghidra.program.model.block.CodeBlock) -> bool: true if basic block contains enough moves of constant bytes to the stack """ count = 0 - for insn in listing.getInstructions(bb, True): + for insn in currentProgram().getListing().getInstructions(bb, True): # type: ignore [name-defined] # noqa: F821 if is_mov_imm_to_stack(insn): count += get_printable_len(insn.getScalar(1)) if count > MIN_STACKSTRING_LEN: @@ -91,7 +88,8 @@ def _bb_has_tight_loop(bb: ghidra.program.model.block.CodeBlock): """ parse tight loops, true if last instruction in basic block branches to bb start """ - last_insn = listing.getInstructions(bb, False).next() # Reverse Ordered, first InstructionDB + # Reverse Ordered, first InstructionDB + last_insn = currentProgram().getListing().getInstructions(bb, False).next() # type: ignore [name-defined] # noqa: F821 if last_insn.getFlowType().isJump(): return last_insn.getAddress(0) == bb.getMinAddress() diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py index 83a6716a5..36c4a9945 100644 --- a/capa/features/extractors/ghidra/extractor.py +++ b/capa/features/extractors/ghidra/extractor.py @@ -16,9 +16,6 @@ from capa.features.address import Address, AbsoluteVirtualAddress from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle, FeatureExtractor -currentProgram = currentProgram() # type: ignore # noqa: F821 -currentAddress = currentAddress() # type: ignore # noqa: F821 - class GhidraFeatureExtractor(FeatureExtractor): def __init__(self): @@ -29,7 +26,7 @@ def __init__(self): self.global_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) def get_base_address(self): - return AbsoluteVirtualAddress(currentProgram.getImageBase().getOffset()) # type: ignore [name-defined] # noqa: F821 + return AbsoluteVirtualAddress(currentProgram().getImageBase().getOffset()) # type: ignore [name-defined] # noqa: F821 def extract_global_features(self): yield from self.global_features @@ -44,8 +41,7 @@ def get_functions(self) -> Iterator[FunctionHandle]: @staticmethod def get_function(addr: int) -> FunctionHandle: - get_addr = currentAddress.getAddress(hex(addr)) # type: ignore [name-defined] # noqa: F821 - func = getFunctionContaining(get_addr) # type: ignore [name-defined] # noqa: F821 + func = getFunctionContaining(toAddr(addr)) # type: ignore [name-defined] # noqa: F821 return FunctionHandle(address=AbsoluteVirtualAddress(func.getAddress().getOffset()), inner=func) def extract_function_features(self, fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]: diff --git a/capa/features/extractors/ghidra/file.py b/capa/features/extractors/ghidra/file.py index f3da41f9d..4de925dad 100644 --- a/capa/features/extractors/ghidra/file.py +++ b/capa/features/extractors/ghidra/file.py @@ -19,7 +19,6 @@ from capa.features.common import FORMAT_PE, FORMAT_ELF, Format, String, Feature, Characteristic from capa.features.address import NO_ADDRESS, Address, FileOffsetAddress, AbsoluteVirtualAddress -currentProgram = currentProgram() # type: ignore # noqa: F821 MAX_OFFSET_PE_AFTER_MZ = 0x200 @@ -46,7 +45,7 @@ def check_segment_for_pe() -> Iterator[Tuple[int, int]]: for off in capa.features.extractors.ghidra.helpers.find_byte_sequence(mzx): todo.append((off, mzx, pex, i)) - seg_max = currentProgram.getMaxAddress() # type: ignore [name-defined] # noqa: F821 + seg_max = currentProgram().getMaxAddress() # type: ignore [name-defined] # noqa: F821 while len(todo): off, mzx, pex, i = todo.pop() @@ -81,7 +80,7 @@ def extract_file_embedded_pe() -> Iterator[Tuple[Feature, Address]]: def extract_file_export_names() -> Iterator[Tuple[Feature, Address]]: """extract function exports""" - st = currentProgram.getSymbolTable() # type: ignore [name-defined] # noqa: F821 + st = currentProgram().getSymbolTable() # type: ignore [name-defined] # noqa: F821 for addr in st.getExternalEntryPointIterator(): yield Export(st.getPrimarySymbol(addr).getName()), AbsoluteVirtualAddress(addr.getOffset()) @@ -98,7 +97,7 @@ def extract_file_import_names() -> Iterator[Tuple[Feature, Address]]: - importname """ - for f in currentProgram.getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 + for f in currentProgram().getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 for r in f.getSymbol().getReferences(): if r.getReferenceType().isData(): addr = r.getFromAddress().getOffset() # gets pointer to fake external addr @@ -114,14 +113,14 @@ def extract_file_import_names() -> Iterator[Tuple[Feature, Address]]: def extract_file_section_names() -> Iterator[Tuple[Feature, Address]]: """extract section names""" - for block in currentProgram.getMemory().getBlocks(): # type: ignore [name-defined] # noqa: F821 + for block in currentProgram().getMemory().getBlocks(): # type: ignore [name-defined] # noqa: F821 yield Section(block.getName()), AbsoluteVirtualAddress(block.getStart().getOffset()) def extract_file_strings() -> Iterator[Tuple[Feature, Address]]: """extract ASCII and UTF-16 LE strings""" - for block in currentProgram.getMemory().getBlocks(): # type: ignore [name-defined] # noqa: F821 + for block in currentProgram().getMemory().getBlocks(): # type: ignore [name-defined] # noqa: F821 if block.isInitialized(): p_bytes = capa.features.extractors.ghidra.helpers.get_block_bytes(block) @@ -139,7 +138,7 @@ def extract_file_function_names() -> Iterator[Tuple[Feature, Address]]: extract the names of statically-linked library functions. """ - for sym in currentProgram.getSymbolTable().getAllSymbols(True): # type: ignore [name-defined] # noqa: F821 + for sym in currentProgram().getSymbolTable().getAllSymbols(True): # type: ignore [name-defined] # noqa: F821 # .isExternal() misses more than this config for the function symbols if sym.getSymbolType() == SymbolType.FUNCTION and sym.getSource() == SourceType.ANALYSIS and sym.isGlobal(): name = sym.getName() # starts to resolve names based on Ghidra's FidDB @@ -156,7 +155,7 @@ def extract_file_function_names() -> Iterator[Tuple[Feature, Address]]: def extract_file_format() -> Iterator[Tuple[Feature, Address]]: - ef = currentProgram.getExecutableFormat() # type: ignore [name-defined] # noqa: F821 + ef = currentProgram().getExecutableFormat() # type: ignore [name-defined] # noqa: F821 if "PE" in ef: yield Format(FORMAT_PE), NO_ADDRESS elif "ELF" in ef: diff --git a/capa/features/extractors/ghidra/function.py b/capa/features/extractors/ghidra/function.py index 3f9c956ce..d31ba86a6 100644 --- a/capa/features/extractors/ghidra/function.py +++ b/capa/features/extractors/ghidra/function.py @@ -16,9 +16,6 @@ from capa.features.extractors import loops from capa.features.extractors.base_extractor import FunctionHandle -currentProgram = currentProgram() # type: ignore # noqa: F821 -monitor = monitor() # type: ignore # noqa: F821 - def extract_function_calls_to(fh: FunctionHandle): """extract callers to a function""" @@ -32,8 +29,8 @@ def extract_function_loop(fh: FunctionHandle): f: ghidra.program.database.function.FunctionDB = fh.inner edges = [] - for block in SimpleBlockIterator(BasicBlockModel(currentProgram), f.getBody(), monitor): # type: ignore [name-defined] # noqa: F821 - dests = block.getDestinations(monitor) # type: ignore [name-defined] # noqa: F821 + for block in SimpleBlockIterator(BasicBlockModel(currentProgram()), f.getBody(), monitor()): # type: ignore [name-defined] # noqa: F821 + dests = block.getDestinations(monitor()) # type: ignore [name-defined] # noqa: F821 s_addrs = block.getStartAddresses() while dests.hasNext(): # For loop throws Python TypeError @@ -47,7 +44,7 @@ def extract_function_loop(fh: FunctionHandle): def extract_recursive_call(fh: FunctionHandle): f: ghidra.program.database.function.FunctionDB = fh.inner - for func in f.getCalledFunctions(monitor): # type: ignore [name-defined] # noqa: F821 + for func in f.getCalledFunctions(monitor()): # type: ignore [name-defined] # noqa: F821 if func.getEntryPoint().getOffset() == f.getEntryPoint().getOffset(): yield Characteristic("recursive call"), AbsoluteVirtualAddress(f.getEntryPoint().getOffset()) diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py index 59797dec9..b2e3093a5 100644 --- a/capa/features/extractors/ghidra/global_.py +++ b/capa/features/extractors/ghidra/global_.py @@ -15,17 +15,16 @@ from capa.features.address import NO_ADDRESS, Address logger = logging.getLogger(__name__) -currentProgram = currentProgram() # type: ignore # noqa: F821 def extract_os() -> Iterator[Tuple[Feature, Address]]: - format_name: str = currentProgram.getExecutableFormat() # type: ignore [name-defined] # noqa: F821 + format_name: str = currentProgram().getExecutableFormat() # type: ignore [name-defined] # noqa: F821 if "PE" in format_name: yield OS(OS_WINDOWS), NO_ADDRESS elif "ELF" in format_name: - program_memory = currentProgram.getMemory() # type: ignore [name-defined] # noqa: F821 + program_memory = currentProgram().getMemory() # type: ignore [name-defined] # noqa: F821 fbytes_list = program_memory.getAllFileBytes() fbytes = fbytes_list[0] @@ -58,7 +57,7 @@ def extract_os() -> Iterator[Tuple[Feature, Address]]: def extract_arch() -> Iterator[Tuple[Feature, Address]]: - lang_id = currentProgram.getMetadata().get("Language ID") # type: ignore [name-defined] # noqa: F821 + lang_id = currentProgram().getMetadata().get("Language ID") # type: ignore [name-defined] # noqa: F821 if "x86" in lang_id and "64" in lang_id: yield Arch(ARCH_AMD64), NO_ADDRESS diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py index 6f520b09e..9cf704852 100644 --- a/capa/features/extractors/ghidra/helpers.py +++ b/capa/features/extractors/ghidra/helpers.py @@ -17,9 +17,6 @@ from capa.features.address import AbsoluteVirtualAddress from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle -monitor = monitor() # type: ignore # noqa: F821 -currentProgram = currentProgram() # type: ignore # noqa: F821 - def fix_byte(b: int) -> bytes: """Transform signed ints from Java into bytes for Python @@ -38,7 +35,7 @@ def find_byte_sequence(seq: bytes) -> Iterator[int]: """ seqstr = "".join([f"\\x{b:02x}" for b in seq]) # .add(1) to avoid false positives on regular PE files - eas = findBytes(currentProgram.getMinAddress().add(1), seqstr, 1, 1) # type: ignore [name-defined] # noqa: F821 + eas = findBytes(currentProgram().getMinAddress().add(1), seqstr, 1, 1) # type: ignore [name-defined] # noqa: F821 yield from eas @@ -80,7 +77,7 @@ def get_block_bytes(block: ghidra.program.model.mem.MemoryBlock) -> bytes: def get_function_symbols() -> Iterator[FunctionHandle]: """yield all non-external function symbols""" - for fhandle in currentProgram.getFunctionManager().getFunctionsNoStubs(True): # type: ignore [name-defined] # noqa: F821 + for fhandle in currentProgram().getFunctionManager().getFunctionsNoStubs(True): # type: ignore [name-defined] # noqa: F821 yield FunctionHandle(address=AbsoluteVirtualAddress(fhandle.getEntryPoint().getOffset()), inner=fhandle) @@ -88,7 +85,7 @@ def get_function_blocks(fh: FunctionHandle) -> Iterator[BBHandle]: """yield BBHandle for each bb in a given function""" func: ghidra.program.database.function.FunctionDB = fh.inner - for bb in SimpleBlockIterator(BasicBlockModel(currentProgram), func.getBody(), monitor): # type: ignore [name-defined] # noqa: F821 + for bb in SimpleBlockIterator(BasicBlockModel(currentProgram()), func.getBody(), monitor()): # type: ignore [name-defined] # noqa: F821 yield BBHandle(address=AbsoluteVirtualAddress(bb.getMinAddress().getOffset()), inner=bb) @@ -107,7 +104,7 @@ def get_file_imports() -> Dict[int, List[str]]: import_dict: Dict[int, List[str]] = {} - for f in currentProgram.getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 + for f in currentProgram().getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 for r in f.getSymbol().getReferences(): if r.getReferenceType().isData(): addr = r.getFromAddress().getOffset() # gets pointer to fake external addr @@ -138,7 +135,7 @@ def get_file_externs() -> Dict[int, List[str]]: extern_dict: Dict[int, List[str]] = {} - for sym in currentProgram.getSymbolTable().getAllSymbols(True): # type: ignore [name-defined] # noqa: F821 + for sym in currentProgram().getSymbolTable().getAllSymbols(True): # type: ignore [name-defined] # noqa: F821 # .isExternal() misses more than this config for the function symbols if sym.getSymbolType() == SymbolType.FUNCTION and sym.getSource() == SourceType.ANALYSIS and sym.isGlobal(): name = sym.getName() # starts to resolve names based on Ghidra's FidDB @@ -176,7 +173,7 @@ def map_fake_import_addrs() -> Dict[int, List[int]]: """ fake_dict: Dict[int, List[int]] = {} - for f in currentProgram.getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 + for f in currentProgram().getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 for r in f.getSymbol().getReferences(): if r.getReferenceType().isData(): fake_dict.setdefault(f.getEntryPoint().getOffset(), []).append(r.getFromAddress().getOffset()) @@ -200,7 +197,7 @@ def get_external_locs() -> List[int]: - 0x000b34EC -> External Location """ locs = [] - for fh in currentProgram.getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 + for fh in currentProgram().getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 external_loc = fh.getExternalLocation().getAddress() if external_loc: locs.append(external_loc) diff --git a/capa/features/extractors/ghidra/insn.py b/capa/features/extractors/ghidra/insn.py index 9c77286f8..bf7334726 100644 --- a/capa/features/extractors/ghidra/insn.py +++ b/capa/features/extractors/ghidra/insn.py @@ -21,8 +21,6 @@ # security cookie checks may perform non-zeroing XORs, these are expected within a certain # byte range within the first and returning basic blocks, this helps to reduce FP features SECURITY_COOKIE_BYTES_DELTA = 0x40 -currentProgram = currentProgram() # type: ignore # noqa: F821 -monitor = monitor() # type: ignore # noqa: F821 # significantly cut down on runtime by caching api info imports = capa.features.extractors.ghidra.helpers.get_file_imports() @@ -375,13 +373,17 @@ def check_nzxor_security_cookie_delta( Check the last bb of the function containing the insn """ - model = SimpleBlockModel(currentProgram) # type: ignore [name-defined] # noqa: F821 + model = SimpleBlockModel(currentProgram()) # type: ignore [name-defined] # noqa: F821 insn_addr = insn.getAddress() func_asv = fh.getBody() first_addr = func_asv.getMinAddress() last_addr = func_asv.getMaxAddress() - if model.getFirstCodeBlockContaining(first_addr, monitor) == model.getFirstCodeBlockContaining(last_addr, monitor): # type: ignore [name-defined] # noqa: F821 + if model.getFirstCodeBlockContaining( + first_addr, monitor() # type: ignore [name-defined] # noqa: F821 + ) == model.getFirstCodeBlockContaining( + last_addr, monitor() # type: ignore [name-defined] # noqa: F821 + ): if insn_addr < first_addr.add(SECURITY_COOKIE_BYTES_DELTA): return True else: diff --git a/tests/fixtures.py b/tests/fixtures.py index 0dd6ea59b..d2339f1ed 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -180,6 +180,16 @@ def get_binja_extractor(path: Path): return extractor +@lru_cache(maxsize=1) +def get_ghidra_extractor(path: Path): + import capa.features.extractors.ghidra.extractor + + extractor = capa.features.extractors.ghidra.extractor.GhidraFeatureExtractor() + setattr(extractor, "path", path.as_posix()) + + return extractor + + def extract_global_features(extractor): features = collections.defaultdict(set) for feature, va in extractor.extract_global_features(): @@ -357,7 +367,7 @@ def get_sample_md5_by_name(name): elif name.startswith("3b13b"): # file name is SHA256 hash return "56a6ffe6a02941028cc8235204eef31d" - elif name == "7351f.elf": + elif name.startswith("7351f"): return "7351f8a40c5450557b24622417fc478d" elif name.startswith("79abd"): return "79abd17391adc6251ecdc58d13d76baf" diff --git a/tests/test_ghidra_features.py b/tests/test_ghidra_features.py new file mode 100644 index 000000000..cbd05782d --- /dev/null +++ b/tests/test_ghidra_features.py @@ -0,0 +1,89 @@ +# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: [package root]/LICENSE.txt +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and limitations under the License. +""" +Must invoke this script from within the Ghidra Runtime Enviornment +""" +import sys +import logging + +import pytest +import fixtures + +logger = logging.getLogger("test_ghidra_features") + +ghidra_present: bool = False +try: + import ghidra # noqa: F401 + + ghidra_present = True +except ImportError: + pass + + +def standardize_posix_str(psx_str): + """fixture test passes the PosixPath to the test data + + params: psx_str - PosixPath() to the test data + return: string that matches test-id sample name + """ + + if "Practical Malware Analysis Lab" in str(psx_str): + # /'Practical Malware Analysis Lab 16-01.exe_' -> 'pma16-01' + wanted_str = "pma" + str(psx_str).split("/")[-1][len("Practical Malware Analysis Lab ") : -5] + else: + # /mimikatz.exe_ -> mimikatz + wanted_str = str(psx_str).split("/")[-1][:-5] + + if "_" in wanted_str: + # al-khaser_x86 -> al-khaser x86 + wanted_str = wanted_str.replace("_", " ") + + return wanted_str + + +def check_input_file(wanted): + """check that test is running on the loaded sample + + params: wanted - PosixPath() passed from test arg + """ + + import capa.ghidra.helpers as ghidra_helpers + + found = ghidra_helpers.get_file_md5() + sample_name = standardize_posix_str(wanted) + + if not found.startswith(fixtures.get_sample_md5_by_name(sample_name)): + raise RuntimeError(f"please run the tests against sample with MD5: `{found}`") + + +@pytest.mark.skipif(ghidra_present is False, reason="Ghidra tests must be ran within Ghidra") +@fixtures.parametrize("sample,scope,feature,expected", fixtures.FEATURE_PRESENCE_TESTS, indirect=["sample", "scope"]) +def test_ghidra_features(sample, scope, feature, expected): + try: + check_input_file(sample) + except RuntimeError: + pytest.skip(reason="Test must be ran against sample loaded in Ghidra") + + fixtures.do_test_feature_presence(fixtures.get_ghidra_extractor, sample, scope, feature, expected) + + +@pytest.mark.skipif(ghidra_present is False, reason="Ghidra tests must be ran within Ghidra") +@fixtures.parametrize("sample,scope,feature,expected", fixtures.FEATURE_COUNT_TESTS, indirect=["sample", "scope"]) +def test_ghidra_feature_counts(sample, scope, feature, expected): + try: + check_input_file(sample) + except RuntimeError: + pytest.skip(reason="Test must be ran against sample loaded in Ghidra") + + fixtures.do_test_feature_count(fixtures.get_ghidra_extractor, sample, scope, feature, expected) + + +if __name__ == "__main__": + # No support for faulthandler module in Ghidrathon, see: + # https://github.com/mandiant/Ghidrathon/issues/70 + sys.exit(pytest.main(["--pyargs", "-p no:faulthandler", "test_ghidra_features"])) From 19b8000c004984045628d62826436fb471e54cfa Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Wed, 23 Aug 2023 13:35:18 -0700 Subject: [PATCH 25/46] Ghidra: Fixes & Enhancements (#1733) * restore from corrupted .git * lint repo * temp: remove lint failing rule * implement dereferencing, clean up extractors * implement proper dereferencing routines as applicable * fix nzxor implementation, remediate ghidra analysis issues * lint repo * Assert typing, lint repo * avoid extracting pointers in bytes extraction * attempt to recover submodule * implement GhidraFeatureExtractor & ghidra_main() * lint repo * document examples, clean-up & testing * lint repo * properly map import dict * properly map fake addresses * fix fake addr mapping * properly map externs * re-align consistency with other backends * lint repo * fix dereferencing routine * clean up helpers * fix format string * disable progress bar to exit gracefully * enable pbar in headless runtime mode * implement fixture test script * implement ghidra unit test script * refactor repo for breaking Ghidrathon change * bump ghidrathon CI version, run unit test in CI * change CI config * fix wget line for ghidrathon * fix unzip paths * fix ghidra import issue * disable pytest faulthandler module * fix dereference function * fix ghidra state variables * implement dereferencing for string extraction * use toAddr * restructure for consistency * Bump Ghidrathon version for CI, fix pytest ghidra runtime detection * fix number & offset extractors * yield both signed & unsgned values for offset extraction * add LEA insn handling to number & offset extraction * fix indirect call extraction * implement thunk function checking for dereferences * revise ghidra feature count tests, pass unit testing * fix feature test format * implement additional support for dereferencing thunked functions * integrate external locations into find_file_imports * change api yield string for .elf samples to match other extractors * fix potential NoneType errors during dereferencing * user helper in global_ * fix GHIDRAIO class, implement in global_ * comment on getOriginalByte * simplify get_file_imports * implement explicit thunk chain handling * simplify LEA number extraction * simplify thunk handling * temp: demonstrate CI failure & output * fix log path * run new test against mimikatz --- .github/workflows/tests.yml | 6 +- capa/features/extractors/elf.py | 2 +- capa/features/extractors/ghidra/global_.py | 17 +---- capa/features/extractors/ghidra/helpers.py | 71 ++++++++++-------- capa/features/extractors/ghidra/insn.py | 87 ++++++++++++++-------- capa/ghidra/helpers.py | 55 ++++++++------ tests/fixtures.py | 8 ++ tests/test_ghidra_features.py | 4 +- 8 files changed, 148 insertions(+), 102 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6b0f7dd0f..9b18f8f62 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -194,5 +194,9 @@ jobs: - name: Install capa run: pip install -e .[dev] - name: Run tests - run: .github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC/support/analyzeHeadless .github/ghidra/project ghidra_test -Import ./tests/data/'mimikatz.exe_' -ScriptPath ./tests/ -PostScript test_ghidra_features.py + run: | + .github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC/support/analyzeHeadless .github/ghidra/project ghidra_test -Import ./tests/data/mimikatz.exe_ -ScriptPath ./tests/ -PostScript test_ghidra_features.py > ../output.log + cat ../output.log + exit_code=$(cat ../output.log | grep exit | awk '{print $NF}') + exit $exit_code diff --git a/capa/features/extractors/elf.py b/capa/features/extractors/elf.py index f9558c1b1..bad8543e8 100644 --- a/capa/features/extractors/elf.py +++ b/capa/features/extractors/elf.py @@ -898,7 +898,7 @@ def guess_os_from_symtab(elf: ELF) -> Optional[OS]: def detect_elf_os(f) -> str: """ - f: type Union[BinaryIO, IDAIO] + f: type Union[BinaryIO, IDAIO, GHIDRAIO] """ try: elf = ELF(f) diff --git a/capa/features/extractors/ghidra/global_.py b/capa/features/extractors/ghidra/global_.py index b2e3093a5..0df58a084 100644 --- a/capa/features/extractors/ghidra/global_.py +++ b/capa/features/extractors/ghidra/global_.py @@ -7,10 +7,11 @@ # See the License for the specific language governing permissions and limitations under the License. import logging import contextlib -from io import BytesIO from typing import Tuple, Iterator +import capa.ghidra.helpers import capa.features.extractors.elf +import capa.features.extractors.ghidra.helpers from capa.features.common import OS, ARCH_I386, ARCH_AMD64, OS_WINDOWS, Arch, Feature from capa.features.address import NO_ADDRESS, Address @@ -24,19 +25,7 @@ def extract_os() -> Iterator[Tuple[Feature, Address]]: yield OS(OS_WINDOWS), NO_ADDRESS elif "ELF" in format_name: - program_memory = currentProgram().getMemory() # type: ignore [name-defined] # noqa: F821 - fbytes_list = program_memory.getAllFileBytes() - fbytes = fbytes_list[0] - - # Java likes to return signed ints, so we must convert them - # back into unsigned bytes manually and write to BytesIO - # note: May be deprecated if Jep has implements better support for Java Lists - pb_arr = b"" - for i in range(fbytes.getSize()): - pb_arr = pb_arr + (fbytes.getOriginalByte(i) & 0xFF).to_bytes(1, "little") - buf = BytesIO(pb_arr) - - with contextlib.closing(buf) as f: + with contextlib.closing(capa.ghidra.helpers.GHIDRAIO()) as f: os = capa.features.extractors.elf.detect_elf_os(f) yield OS(os), NO_ADDRESS diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py index 9cf704852..b2f1238eb 100644 --- a/capa/features/extractors/ghidra/helpers.py +++ b/capa/features/extractors/ghidra/helpers.py @@ -14,6 +14,7 @@ from ghidra.program.model.address import AddressSpace import capa.features.extractors.helpers +from capa.features.common import THUNK_CHAIN_DEPTH_DELTA from capa.features.address import AbsoluteVirtualAddress from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle @@ -109,12 +110,19 @@ def get_file_imports() -> Dict[int, List[str]]: if r.getReferenceType().isData(): addr = r.getFromAddress().getOffset() # gets pointer to fake external addr - fstr = f.toString().split("::") # format: MODULE.dll::import / MODULE::Ordinal_* + ex_loc = f.getExternalLocation().getAddress() # map external locations as well (offset into module files) + + fstr = f.toString().split("::") # format: MODULE.dll::import / MODULE::Ordinal_* / ::import if "Ordinal_" in fstr[1]: fstr[1] = f"#{fstr[1].split('_')[1]}" - for name in capa.features.extractors.helpers.generate_symbols(fstr[0][:-4], fstr[1]): + # mostly shows up in ELF files, otherwise, strip '.dll' w/ [:-4] + fstr[0] = "*" if "" in fstr[0] else fstr[0][:-4] + + for name in capa.features.extractors.helpers.generate_symbols(fstr[0], fstr[1]): import_dict.setdefault(addr, []).append(name) + if ex_loc: + import_dict.setdefault(ex_loc.getOffset(), []).append(name) return import_dict @@ -181,35 +189,11 @@ def map_fake_import_addrs() -> Dict[int, List[int]]: return fake_dict -def get_external_locs() -> List[int]: - """ - Helps to discern external offsets from regular bytes when extracting - data. - - Ghidra behavior: - - Offsets that point to specific sections of external programs - i.e. library code. - - Stored in data, and pointed to by an absolute address - https://github.com/NationalSecurityAgency/ghidra/blob/26d4bd9104809747c21f2528cab8aba9aef9acd5/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/ExternalLocation.java#L25-30 - - Example: (mimikatz.exe_) 5f66b82558ca92e54e77f216ef4c066c:0x473090 - - 0x473090 -> PTR_CreateServiceW_00473090 - - 0x000b34EC -> External Location - """ - locs = [] - for fh in currentProgram().getFunctionManager().getExternalFunctions(): # type: ignore [name-defined] # noqa: F821 - external_loc = fh.getExternalLocation().getAddress() - if external_loc: - locs.append(external_loc) - return locs - - def check_addr_for_api( addr: ghidra.program.model.address.Address, fakes: Dict[int, List[int]], imports: Dict[int, List[str]], externs: Dict[int, List[str]], - ex_locs: List[int], ) -> bool: offset = addr.getOffset() @@ -225,9 +209,6 @@ def check_addr_for_api( if extern: return True - if addr in ex_locs: - return True - return False @@ -244,6 +225,13 @@ def is_sp_modified(insn: ghidra.program.database.code.InstructionDB) -> bool: def is_stack_referenced(insn: ghidra.program.database.code.InstructionDB) -> bool: """generic catch-all for stack references""" + for i in range(insn.getNumOperands()): + if insn.getOperandType(i) == OperandType.REGISTER: + if "BP" in insn.getRegister(i).getName(): + return True + else: + continue + return any(ref.isStackReference() for ref in insn.getReferencesFrom()) @@ -263,9 +251,34 @@ def is_zxor(insn: ghidra.program.database.code.InstructionDB) -> bool: return all(n == operands[0] for n in operands) +def handle_thunk(addr: ghidra.program.model.address.Address): + """Follow thunk chains down to a reasonable depth""" + ref = addr + for _ in range(THUNK_CHAIN_DEPTH_DELTA): + thunk_jmp = getInstructionAt(ref) # type: ignore [name-defined] # noqa: F821 + if thunk_jmp and is_call_or_jmp(thunk_jmp): + if OperandType.isAddress(thunk_jmp.getOperandType(0)): + ref = thunk_jmp.getAddress(0) + else: + thunk_dat = getDataContaining(ref) # type: ignore [name-defined] # noqa: F821 + if thunk_dat and thunk_dat.isDefined() and thunk_dat.isPointer(): + ref = thunk_dat.getValue() + break # end of thunk chain reached + return ref + + def dereference_ptr(insn: ghidra.program.database.code.InstructionDB): + addr_code = OperandType.ADDRESS | OperandType.CODE to_deref = insn.getAddress(0) dat = getDataContaining(to_deref) # type: ignore [name-defined] # noqa: F821 + + if insn.getOperandType(0) == addr_code: + thfunc = getFunctionContaining(to_deref) # type: ignore [name-defined] # noqa: F821 + if thfunc and thfunc.isThunk(): + return handle_thunk(to_deref) + else: + # if it doesn't poin to a thunk, it's usually a jmp to a label + return to_deref if not dat: return to_deref if dat.isDefined() and dat.isPointer(): diff --git a/capa/features/extractors/ghidra/insn.py b/capa/features/extractors/ghidra/insn.py index bf7334726..17fb9cc08 100644 --- a/capa/features/extractors/ghidra/insn.py +++ b/capa/features/extractors/ghidra/insn.py @@ -26,7 +26,6 @@ imports = capa.features.extractors.ghidra.helpers.get_file_imports() externs = capa.features.extractors.ghidra.helpers.get_file_externs() mapped_fake_addrs = capa.features.extractors.ghidra.helpers.map_fake_import_addrs() -external_locs = capa.features.extractors.ghidra.helpers.get_external_locs() def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: @@ -36,6 +35,7 @@ def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: # assume only CALLs or JMPs are passed ref_type = insn.getOperandType(0) addr_data = OperandType.ADDRESS | OperandType.DATA # needs dereferencing + addr_code = OperandType.ADDRESS | OperandType.CODE # needs dereferencing if OperandType.isRegister(ref_type): if OperandType.isAddress(ref_type): @@ -47,23 +47,21 @@ def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: return else: return - elif ref_type == addr_data: + elif ref_type in (addr_data, addr_code) or OperandType.isIndirect(ref_type): # we must dereference and check if the addr is a pointer to an api function addr_ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn) if not capa.features.extractors.ghidra.helpers.check_addr_for_api( - addr_ref, mapped_fake_addrs, imports, externs, external_locs + addr_ref, mapped_fake_addrs, imports, externs ): return ref = addr_ref.getOffset() elif ref_type == OperandType.DYNAMIC | OperandType.ADDRESS or ref_type == OperandType.DYNAMIC: return # cannot resolve dynamics statically - elif OperandType.isIndirect(ref_type): - return # cannot resolve the indirection statically else: # pure address does not need to get dereferenced/ handled addr_ref = insn.getAddress(0) if not capa.features.extractors.ghidra.helpers.check_addr_for_api( - addr_ref, mapped_fake_addrs, imports, externs, external_locs + addr_ref, mapped_fake_addrs, imports, externs ): return ref = addr_ref.getOffset() @@ -115,25 +113,40 @@ def extract_insn_number_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandl return for i in range(insn.getNumOperands()): - if insn.getOperandType(i) != OperandType.SCALAR: + # Exceptions for LEA insn: + # invalid operand encoding, considered numbers instead of offsets + # see: mimikatz.exe_:0x4018C0 + if insn.getOperandType(i) == OperandType.DYNAMIC and insn.getMnemonicString().startswith("LEA"): + # Additional check, avoid yielding "wide" values (ex. mimikatz.exe:0x471EE6 LEA EBX, [ECX + EAX*0x4]) + op_objs = insn.getOpObjects(i) + if len(op_objs) == 3: # ECX, EAX, 0x4 + continue + + if isinstance(op_objs[-1], ghidra.program.model.scalar.Scalar): + const = op_objs[-1].getUnsignedValue() + addr = ih.address + + yield Number(const), addr + yield OperandNumber(i, const), addr + elif not OperandType.isScalar(insn.getOperandType(i)): # skip things like: # references, void types continue + else: + const = insn.getScalar(i).getUnsignedValue() + addr = ih.address - const = insn.getScalar(i).getValue() - addr = ih.address - - yield Number(const), addr - yield OperandNumber(i, const), addr + yield Number(const), addr + yield OperandNumber(i, const), addr - if insn.getMnemonicString().startswith("ADD") and 0 < const < MAX_STRUCTURE_SIZE: - # for pattern like: - # - # add eax, 0x10 - # - # assume 0x10 is also an offset (imagine eax is a pointer). - yield Offset(const), addr - yield OperandOffset(i, const), addr + if insn.getMnemonicString().startswith("ADD") and 0 < const < MAX_STRUCTURE_SIZE: + # for pattern like: + # + # add eax, 0x10 + # + # assume 0x10 is also an offset (imagine eax is a pointer). + yield Offset(const), addr + yield OperandOffset(i, const), addr def extract_insn_offset_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]: @@ -145,6 +158,9 @@ def extract_insn_offset_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandl """ insn: ghidra.program.database.code.InstructionDB = ih.inner + if insn.getMnemonicString().startswith("LEA"): + return + # ignore any stack references if not capa.features.extractors.ghidra.helpers.is_stack_referenced(insn): # Ghidra stores operands in 2D arrays if they contain offsets @@ -156,6 +172,9 @@ def extract_insn_offset_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandl op_off = op_objs[-1].getValue() yield Offset(op_off), ih.address yield OperandOffset(i, op_off), ih.address + else: + yield Offset(0), ih.address + yield OperandOffset(i, 0), ih.address def extract_insn_bytes_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]: @@ -171,7 +190,7 @@ def extract_insn_bytes_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandle ref = insn.getAddress() # init to insn addr for i in range(insn.getNumOperands()): - if OperandType.isScalarAsAddress(insn.getOperandType(i)): + if OperandType.isAddress(insn.getOperandType(i)): ref = insn.getAddress(i) # pulls pointer if there is one if ref != insn.getAddress(): # bail out if there's no pointer @@ -193,11 +212,18 @@ def extract_insn_string_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandl push offset aAcr ; "ACR > " """ insn: ghidra.program.database.code.InstructionDB = ih.inner + dyn_addr = OperandType.DYNAMIC | OperandType.ADDRESS ref = insn.getAddress() for i in range(insn.getNumOperands()): if OperandType.isScalarAsAddress(insn.getOperandType(i)): ref = insn.getAddress(i) + # strings are also referenced dynamically via pointers & arrays, so we need to deref them + if insn.getOperandType(i) == dyn_addr: + ref = insn.getAddress(i) + dat = getDataAt(ref) # type: ignore [name-defined] # noqa: F821 + if dat and dat.isPointer(): + ref = dat.getValue() if ref != insn.getAddress(): ghidra_dat = getDataAt(ref) # type: ignore [name-defined] # noqa: F821 @@ -277,6 +303,7 @@ def extract_insn_cross_section_cflow( # OperandType to dereference addr_data = OperandType.ADDRESS | OperandType.DATA + addr_code = OperandType.ADDRESS | OperandType.CODE ref_type = insn.getOperandType(0) @@ -285,29 +312,21 @@ def extract_insn_cross_section_cflow( if OperandType.isRegister(ref_type): if OperandType.isAddress(ref_type): ref = insn.getAddress(0) # Ghidra dereferences REG | ADDR - if capa.features.extractors.ghidra.helpers.check_addr_for_api( - ref, mapped_fake_addrs, imports, externs, external_locs - ): + if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, mapped_fake_addrs, imports, externs): return else: return - elif ref_type == addr_data: + elif ref_type in (addr_data, addr_code) or OperandType.isIndirect(ref_type): # we must dereference and check if the addr is a pointer to an api function ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn) - if capa.features.extractors.ghidra.helpers.check_addr_for_api( - ref, mapped_fake_addrs, imports, externs, external_locs - ): + if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, mapped_fake_addrs, imports, externs): return elif ref_type == OperandType.DYNAMIC | OperandType.ADDRESS or ref_type == OperandType.DYNAMIC: return # cannot resolve dynamics statically - elif OperandType.isIndirect(ref_type): - return # cannot resolve the indirection statically else: # pure address does not need to get dereferenced/ handled ref = insn.getAddress(0) - if capa.features.extractors.ghidra.helpers.check_addr_for_api( - ref, mapped_fake_addrs, imports, externs, external_locs - ): + if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, mapped_fake_addrs, imports, externs): return this_mem_block = getMemoryBlock(insn.getAddress()) # type: ignore [name-defined] # noqa: F821 @@ -359,6 +378,8 @@ def extract_function_indirect_call_characteristic_features( insn: ghidra.program.database.code.InstructionDB = ih.inner if insn.getMnemonicString().startswith("CALL"): + if OperandType.isRegister(insn.getOperandType(0)): + yield Characteristic("indirect call"), ih.address if OperandType.isIndirect(insn.getOperandType(0)): yield Characteristic("indirect call"), ih.address diff --git a/capa/ghidra/helpers.py b/capa/ghidra/helpers.py index ffe0d3738..a9ddebad9 100644 --- a/capa/ghidra/helpers.py +++ b/capa/ghidra/helpers.py @@ -20,9 +20,6 @@ logger = logging.getLogger("capa") -currentProgram = currentProgram() # type: ignore # noqa: F821 -currentAddress = currentAddress() # type: ignore # noqa: F821 - # file type as returned by Ghidra SUPPORTED_FILE_TYPES = ("Executable and Linking Format (ELF)", "Portable Executable (PE)", "Raw Binary") @@ -36,29 +33,41 @@ class GHIDRAIO: def __init__(self): super().__init__() self.offset = 0 + self.bytez = self.get_file_bytes() def seek(self, offset, whence=0): assert whence == 0 self.offset = offset def read(self, size): - try: - # ghidra.program.model.address.Address has no public constructor, - # so we have to use the exposed currentAddress object for its - # member function .getAddress() - ea = currentAddress.getAddress(hex(self.offset)) # type: ignore [name-defined] # noqa: F821 - except RuntimeError: # AddressFormatException to Ghidra + logger.debug("reading 0x%x bytes at 0x%x (ea: 0x%x)", size, self.offset, currentProgram().getImageBase().add(self.offset).getOffset()) # type: ignore [name-defined] # noqa: F821 + + b_len = len(self.bytez) + if size > b_len - self.offset: logger.debug("cannot read 0x%x bytes at 0x%x (ea: BADADDR)", size, self.offset) return b"" - - logger.debug("reading 0x%x bytes at 0x%x (ea: 0x%x)", size, self.offset, ea.getOffset()) - - # returns bytes or b"" - return capa.features.extractors.ghidra.helpers.get_bytes(ea, size) + else: + read_bytes = b"" + read = [ + capa.features.extractors.ghidra.helpers.fix_byte(b) + for b in self.bytez[self.offset : self.offset + size] + ] + for b in read: + read_bytes = read_bytes + b + return read_bytes def close(self): return + def get_file_bytes(self): + fbytes = currentProgram().getMemory().getAllFileBytes()[0] # type: ignore [name-defined] # noqa: F821 + bytez = b"" + for i in range(fbytes.getSize()): + # getOriginalByte() allows for raw file parsing on the Ghidra side + # other functions will fail as Ghidra will think that it's reading uninitialized memory + bytez = bytez + capa.features.extractors.ghidra.helpers.fix_byte(fbytes.getOriginalByte(i)) + return bytez + def is_supported_ghidra_version(): version = float(getGhidraVersion()[:4]) # type: ignore [name-defined] # noqa: F821 @@ -75,7 +84,7 @@ def is_running_headless(): def is_supported_file_type(): - file_info = currentProgram.getExecutableFormat() # type: ignore [name-defined] # noqa: F821 + file_info = currentProgram().getExecutableFormat() # type: ignore [name-defined] # noqa: F821 if file_info.filetype not in SUPPORTED_FILE_TYPES: logger.error("-" * 80) logger.error(" Input file does not appear to be a supported file type.") @@ -90,7 +99,7 @@ def is_supported_file_type(): def is_supported_arch_type(): - file_info = currentProgram.getLanguageID() # type: ignore [name-defined] # noqa: F821 + file_info = currentProgram().getLanguageID() # type: ignore [name-defined] # noqa: F821 if "x86" not in file_info or not any(arch in file_info for arch in ["32", "64"]): logger.error("-" * 80) logger.error(" Input file does not appear to target a supported architecture.") @@ -102,18 +111,18 @@ def is_supported_arch_type(): def get_file_md5(): - return currentProgram.getExecutableMD5() # type: ignore [name-defined] # noqa: F821 + return currentProgram().getExecutableMD5() # type: ignore [name-defined] # noqa: F821 def get_file_sha256(): - return currentProgram.getExecutableSHA256() # type: ignore [name-defined] # noqa: F821 + return currentProgram().getExecutableSHA256() # type: ignore [name-defined] # noqa: F821 def collect_metadata(rules: List[Path]): md5 = get_file_md5() sha256 = get_file_sha256() - info = currentProgram.getLanguageID().toString() # type: ignore [name-defined] # noqa: F821 + info = currentProgram().getLanguageID().toString() # type: ignore [name-defined] # noqa: F821 if "x86" in info and "64" in info: arch = "x86_64" elif "x86" in info and "32" in info: @@ -121,7 +130,7 @@ def collect_metadata(rules: List[Path]): else: arch = "unknown arch" - format_name: str = currentProgram.getExecutableFormat() # type: ignore [name-defined] # noqa: F821 + format_name: str = currentProgram().getExecutableFormat() # type: ignore [name-defined] # noqa: F821 if "PE" in format_name: os = "windows" elif "ELF" in format_name: @@ -138,15 +147,15 @@ def collect_metadata(rules: List[Path]): md5=md5, sha1="", sha256=sha256, - path=currentProgram.getExecutablePath(), # type: ignore [name-defined] # noqa: F821 + path=currentProgram().getExecutablePath(), # type: ignore [name-defined] # noqa: F821 ), analysis=rdoc.Analysis( - format=currentProgram.getExecutableFormat(), # type: ignore [name-defined] # noqa: F821 + format=currentProgram().getExecutableFormat(), # type: ignore [name-defined] # noqa: F821 arch=arch, os=os, extractor="ghidra", rules=tuple(r.resolve().absolute().as_posix() for r in rules), - base_address=capa.features.freeze.Address.from_capa(currentProgram.getImageBase().getOffset()), # type: ignore [name-defined] # noqa: F821 + base_address=capa.features.freeze.Address.from_capa(currentProgram().getImageBase().getOffset()), # type: ignore [name-defined] # noqa: F821 layout=rdoc.Layout( functions=(), ), diff --git a/tests/fixtures.py b/tests/fixtures.py index d2339f1ed..a8a930b34 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -1063,6 +1063,14 @@ def parametrize(params, values, **kwargs): ] +FEATURE_COUNT_TESTS_GHIDRA = [ + # Ghidra may render functions as labels, as well as provide differing amounts of call references + # (Colton) TODO: Add more test cases + ("mimikatz", "function=0x4702FD", capa.features.common.Characteristic("calls from"), 0), + ("mimikatz", "function=0x4556E5", capa.features.common.Characteristic("calls to"), 0), +] + + def do_test_feature_presence(get_extractor, sample, scope, feature, expected): extractor = get_extractor(sample) features = scope(extractor) diff --git a/tests/test_ghidra_features.py b/tests/test_ghidra_features.py index cbd05782d..0ea1b1a7c 100644 --- a/tests/test_ghidra_features.py +++ b/tests/test_ghidra_features.py @@ -73,7 +73,9 @@ def test_ghidra_features(sample, scope, feature, expected): @pytest.mark.skipif(ghidra_present is False, reason="Ghidra tests must be ran within Ghidra") -@fixtures.parametrize("sample,scope,feature,expected", fixtures.FEATURE_COUNT_TESTS, indirect=["sample", "scope"]) +@fixtures.parametrize( + "sample,scope,feature,expected", fixtures.FEATURE_COUNT_TESTS_GHIDRA, indirect=["sample", "scope"] +) def test_ghidra_feature_counts(sample, scope, feature, expected): try: check_input_file(sample) From 70d36ab6406a46b5bc9c2cac3866a80a8c8ea38d Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Wed, 23 Aug 2023 14:40:15 -0700 Subject: [PATCH 26/46] properly set bounds for find_byte_sequence (#1757) --- capa/features/extractors/ghidra/helpers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py index b2f1238eb..3acae2640 100644 --- a/capa/features/extractors/ghidra/helpers.py +++ b/capa/features/extractors/ghidra/helpers.py @@ -8,6 +8,7 @@ from typing import Dict, List, Iterator import ghidra +import java.lang from ghidra.program.model.lang import OperandType from ghidra.program.model.block import BasicBlockModel, SimpleBlockIterator from ghidra.program.model.symbol import SourceType, SymbolType @@ -36,7 +37,7 @@ def find_byte_sequence(seq: bytes) -> Iterator[int]: """ seqstr = "".join([f"\\x{b:02x}" for b in seq]) # .add(1) to avoid false positives on regular PE files - eas = findBytes(currentProgram().getMinAddress().add(1), seqstr, 1, 1) # type: ignore [name-defined] # noqa: F821 + eas = findBytes(currentProgram().getMinAddress().add(1), seqstr, java.lang.Integer.MAX_VALUE, 1) # type: ignore [name-defined] # noqa: F821 yield from eas From bd2f7bc1f4f724218543c9153d8b9b0c0425d646 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Thu, 24 Aug 2023 22:09:08 +0000 Subject: [PATCH 27/46] hotfix: fix indirect address dereference handling --- capa/features/extractors/ghidra/insn.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/capa/features/extractors/ghidra/insn.py b/capa/features/extractors/ghidra/insn.py index 17fb9cc08..41787cc85 100644 --- a/capa/features/extractors/ghidra/insn.py +++ b/capa/features/extractors/ghidra/insn.py @@ -47,7 +47,7 @@ def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: return else: return - elif ref_type in (addr_data, addr_code) or OperandType.isIndirect(ref_type): + elif ref_type in (addr_data, addr_code) or (OperandType.isIndirect(ref_type) and OperandType.isAddress(ref_type)): # we must dereference and check if the addr is a pointer to an api function addr_ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn) if not capa.features.extractors.ghidra.helpers.check_addr_for_api( @@ -60,6 +60,11 @@ def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: else: # pure address does not need to get dereferenced/ handled addr_ref = insn.getAddress(0) + if not addr_ref: + # If it returned null, it was an indirect + # that had no address reference. + # This check is faster than checking for (indirect and not address) + return if not capa.features.extractors.ghidra.helpers.check_addr_for_api( addr_ref, mapped_fake_addrs, imports, externs ): @@ -316,7 +321,7 @@ def extract_insn_cross_section_cflow( return else: return - elif ref_type in (addr_data, addr_code) or OperandType.isIndirect(ref_type): + elif ref_type in (addr_data, addr_code) or (OperandType.isIndirect(ref_type) and OperandType.isAddress(ref_type)): # we must dereference and check if the addr is a pointer to an api function ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn) if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, mapped_fake_addrs, imports, externs): @@ -326,6 +331,11 @@ def extract_insn_cross_section_cflow( else: # pure address does not need to get dereferenced/ handled ref = insn.getAddress(0) + if not ref: + # If it returned null, it was an indirect + # that had no address reference. + # This check is faster than checking for (indirect and not address) + return if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, mapped_fake_addrs, imports, externs): return From 448b122ef0821af640199912464e979f361ff57a Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Thu, 24 Aug 2023 17:01:41 -0600 Subject: [PATCH 28/46] fix ints_to_bytes performance (#1761) * fix ints_to_bytes performance --- CHANGELOG.md | 1 + capa/features/extractors/ghidra/file.py | 8 ++--- capa/features/extractors/ghidra/helpers.py | 34 +++++++--------------- capa/ghidra/helpers.py | 31 ++++++++------------ 4 files changed, 28 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74623cad4..078b8648a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ - ELF: fix parsing of symtab #1704 @williballenthin - result document: don't use deprecated pydantic functions #1718 @williballenthin - pytest: don't mark IDA tests as pytest tests #1719 @williballenthin +- ghidra: fix ints_to_bytes performance #1761 @mike-hunhoff ### capa explorer IDA Pro plugin - fix unhandled exception when resolving rule path #1693 @mike-hunhoff diff --git a/capa/features/extractors/ghidra/file.py b/capa/features/extractors/ghidra/file.py index 4de925dad..332f87855 100644 --- a/capa/features/extractors/ghidra/file.py +++ b/capa/features/extractors/ghidra/file.py @@ -22,7 +22,7 @@ MAX_OFFSET_PE_AFTER_MZ = 0x200 -def check_segment_for_pe() -> Iterator[Tuple[int, int]]: +def find_embedded_pe() -> Iterator[Tuple[int, int]]: """check segment for embedded PE adapted for Ghidra from: @@ -39,10 +39,11 @@ def check_segment_for_pe() -> Iterator[Tuple[int, int]]: ] todo = [] + start_addr = currentProgram().getMinAddress().add(1) # type: ignore [name-defined] # noqa: F821 for mzx, pex, i in mz_xor: # find all segment offsets containing XOR'd "MZ" bytes off: ghidra.program.model.address.GenericAddress - for off in capa.features.extractors.ghidra.helpers.find_byte_sequence(mzx): + for off in capa.features.extractors.ghidra.helpers.find_byte_sequence(start_addr, mzx): todo.append((off, mzx, pex, i)) seg_max = currentProgram().getMaxAddress() # type: ignore [name-defined] # noqa: F821 @@ -73,8 +74,7 @@ def check_segment_for_pe() -> Iterator[Tuple[int, int]]: def extract_file_embedded_pe() -> Iterator[Tuple[Feature, Address]]: """extract embedded PE features""" - - for ea, _ in check_segment_for_pe(): + for ea, _ in find_embedded_pe(): yield Characteristic("embedded pe"), FileOffsetAddress(ea) diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py index 3acae2640..9324e1004 100644 --- a/capa/features/extractors/ghidra/helpers.py +++ b/capa/features/extractors/ghidra/helpers.py @@ -20,24 +20,25 @@ from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle -def fix_byte(b: int) -> bytes: - """Transform signed ints from Java into bytes for Python +def ints_to_bytes(bytez: List[int]) -> bytes: + """convert Java signed ints to Python bytes args: - b: signed int returned from Java processing + bytez: list of Java signed ints """ - return (b & 0xFF).to_bytes(1, "little") + return bytes([b & 0xFF for b in bytez]) -def find_byte_sequence(seq: bytes) -> Iterator[int]: +def find_byte_sequence(addr: ghidra.program.model.address.Address, seq: bytes) -> Iterator[int]: """yield all ea of a given byte sequence args: + addr: start address seq: bytes to search e.g. b"\x01\x03" """ seqstr = "".join([f"\\x{b:02x}" for b in seq]) - # .add(1) to avoid false positives on regular PE files - eas = findBytes(currentProgram().getMinAddress().add(1), seqstr, java.lang.Integer.MAX_VALUE, 1) # type: ignore [name-defined] # noqa: F821 + eas = findBytes(addr, seqstr, java.lang.Integer.MAX_VALUE, 1) # type: ignore [name-defined] # noqa: F821 + yield from eas @@ -48,15 +49,10 @@ def get_bytes(addr: ghidra.program.model.address.Address, length: int) -> bytes: addr: Address to begin pull from length: length of bytes to pull """ - - bytez = b"" try: - signed_ints = getBytes(addr, length) # type: ignore [name-defined] # noqa: F821 - for b in signed_ints: - bytez = bytez + fix_byte(b) - return bytez + return ints_to_bytes(getBytes(addr, length)) # type: ignore [name-defined] # noqa: F821 except RuntimeError: - return bytez + return b"" def get_block_bytes(block: ghidra.program.model.mem.MemoryBlock) -> bytes: @@ -65,15 +61,7 @@ def get_block_bytes(block: ghidra.program.model.mem.MemoryBlock) -> bytes: args: block: MemoryBlock to pull from """ - - bytez = b"" - try: - signed_ints = getBytes(block.getStart(), block.getEnd().getOffset() - block.getStart().getOffset()) # type: ignore [name-defined] # noqa: F821 - for b in signed_ints: - bytez = bytez + fix_byte(b) - return bytez - except RuntimeError: - return bytez + return get_bytes(block.getStart(), block.getSize()) def get_function_symbols() -> Iterator[FunctionHandle]: diff --git a/capa/ghidra/helpers.py b/capa/ghidra/helpers.py index a9ddebad9..342d4f9ad 100644 --- a/capa/ghidra/helpers.py +++ b/capa/ghidra/helpers.py @@ -32,8 +32,9 @@ class GHIDRAIO: def __init__(self): super().__init__() + self.offset = 0 - self.bytez = self.get_file_bytes() + self.bytes_ = self.get_bytes() def seek(self, offset, whence=0): assert whence == 0 @@ -42,31 +43,23 @@ def seek(self, offset, whence=0): def read(self, size): logger.debug("reading 0x%x bytes at 0x%x (ea: 0x%x)", size, self.offset, currentProgram().getImageBase().add(self.offset).getOffset()) # type: ignore [name-defined] # noqa: F821 - b_len = len(self.bytez) - if size > b_len - self.offset: + if size > len(self.bytes_) - self.offset: logger.debug("cannot read 0x%x bytes at 0x%x (ea: BADADDR)", size, self.offset) return b"" else: - read_bytes = b"" - read = [ - capa.features.extractors.ghidra.helpers.fix_byte(b) - for b in self.bytez[self.offset : self.offset + size] - ] - for b in read: - read_bytes = read_bytes + b - return read_bytes + return self.bytes_[self.offset : self.offset + size] def close(self): return - def get_file_bytes(self): - fbytes = currentProgram().getMemory().getAllFileBytes()[0] # type: ignore [name-defined] # noqa: F821 - bytez = b"" - for i in range(fbytes.getSize()): - # getOriginalByte() allows for raw file parsing on the Ghidra side - # other functions will fail as Ghidra will think that it's reading uninitialized memory - bytez = bytez + capa.features.extractors.ghidra.helpers.fix_byte(fbytes.getOriginalByte(i)) - return bytez + def get_bytes(self): + file_bytes = currentProgram().getMemory().getAllFileBytes()[0] # type: ignore [name-defined] # noqa: F821 + + # getOriginalByte() allows for raw file parsing on the Ghidra side + # other functions will fail as Ghidra will think that it's reading uninitialized memory + bytes_ = [file_bytes.getOriginalByte(i) for i in range(file_bytes.getSize())] + + return capa.features.extractors.ghidra.helpers.ints_to_bytes(bytes_) def is_supported_ghidra_version(): From 65179805a77cd17b5dd8abd5027e8caed312b0f6 Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Fri, 25 Aug 2023 19:35:59 -0600 Subject: [PATCH 29/46] add a Ghidra entry script users can invoke to run capa against a loaded Ghidra database (#1767) * enable use of Ghidra with show-features.py * fix bug in is_supported_file_type * fix bug in GhidraFeatureExtractor.get_function * refactor get_insn_in_range * add Ghidra entry script for users to more easily run capa against a loaded Ghidra database * update CHANGELOG * fixing lint * fix fixtures import issue * fix bug in is_supported_arch_type * add check for supported arch type * fix extract_embedded_pe performance --- CHANGELOG.md | 1 + capa/features/extractors/ghidra/extractor.py | 2 +- capa/features/extractors/ghidra/file.py | 62 +++---- capa/features/extractors/ghidra/helpers.py | 8 +- capa/ghidra/capa_ghidra.py | 166 +++++++++++++++++++ capa/ghidra/helpers.py | 7 +- capa/main.py | 1 + scripts/show-features.py | 17 ++ tests/test_ghidra_features.py | 9 +- 9 files changed, 234 insertions(+), 39 deletions(-) create mode 100644 capa/ghidra/capa_ghidra.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 078b8648a..62722e431 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - ELF: implement file import and export name extractor #1607 #1608 @Aayush-Goel-04 - bump pydantic from 1.10.9 to 2.1.1 #1582 @Aayush-Goel-04 - develop script to highlight the features that are not used during matching #331 @Aayush-Goel-04 +- ghidra: add entry script helping users run capa against a loaded Ghidra database #1767 @mike-hunhoff ### Breaking Changes diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py index 36c4a9945..4034ba50c 100644 --- a/capa/features/extractors/ghidra/extractor.py +++ b/capa/features/extractors/ghidra/extractor.py @@ -42,7 +42,7 @@ def get_functions(self) -> Iterator[FunctionHandle]: @staticmethod def get_function(addr: int) -> FunctionHandle: func = getFunctionContaining(toAddr(addr)) # type: ignore [name-defined] # noqa: F821 - return FunctionHandle(address=AbsoluteVirtualAddress(func.getAddress().getOffset()), inner=func) + return FunctionHandle(address=AbsoluteVirtualAddress(func.getEntryPoint().getOffset()), inner=func) def extract_function_features(self, fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]: yield from capa.features.extractors.ghidra.function.extract_features(fh) diff --git a/capa/features/extractors/ghidra/file.py b/capa/features/extractors/ghidra/file.py index 332f87855..f0bb0d047 100644 --- a/capa/features/extractors/ghidra/file.py +++ b/capa/features/extractors/ghidra/file.py @@ -5,10 +5,10 @@ # Unless required by applicable law or agreed to in writing, software distributed under the License # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and limitations under the License. +import re import struct -from typing import Tuple, Iterator +from typing import List, Tuple, Iterator -import ghidra from ghidra.program.model.symbol import SourceType, SymbolType import capa.features.extractors.common @@ -22,60 +22,66 @@ MAX_OFFSET_PE_AFTER_MZ = 0x200 -def find_embedded_pe() -> Iterator[Tuple[int, int]]: +def find_embedded_pe(block_bytez: bytes, mz_xor: List[Tuple[bytes, bytes, int]]) -> Iterator[Tuple[int, int]]: """check segment for embedded PE adapted for Ghidra from: https://github.com/vivisect/vivisect/blob/91e8419a861f4977https://github.com/vivisect/vivisect/blob/91e8419a861f49779f18316f155311967e696836/PE/carve.py#L259f18316f155311967e696836/PE/carve.py#L25 """ - - mz_xor = [ - ( - capa.features.extractors.helpers.xor_static(b"MZ", i), - capa.features.extractors.helpers.xor_static(b"PE", i), - i, - ) - for i in range(256) - ] - todo = [] - start_addr = currentProgram().getMinAddress().add(1) # type: ignore [name-defined] # noqa: F821 + for mzx, pex, i in mz_xor: - # find all segment offsets containing XOR'd "MZ" bytes - off: ghidra.program.model.address.GenericAddress - for off in capa.features.extractors.ghidra.helpers.find_byte_sequence(start_addr, mzx): - todo.append((off, mzx, pex, i)) + for match in re.finditer(re.escape(mzx), block_bytez): + todo.append((match.start(), mzx, pex, i)) - seg_max = currentProgram().getMaxAddress() # type: ignore [name-defined] # noqa: F821 + seg_max = len(block_bytez) # type: ignore [name-defined] # noqa: F821 while len(todo): off, mzx, pex, i = todo.pop() # MZ header has one field we will check e_lfanew is at 0x3c - e_lfanew = off.add(0x3C) + e_lfanew = off + 0x3C - if seg_max.getOffset() < (e_lfanew.getOffset() + 4): + if seg_max < e_lfanew + 4: continue - e_lfanew_bytes = capa.features.extractors.ghidra.helpers.get_bytes(e_lfanew, 4) + e_lfanew_bytes = block_bytez[e_lfanew : e_lfanew + 4] newoff = struct.unpack(" MAX_OFFSET_PE_AFTER_MZ: continue - peoff = off.add(newoff) - if seg_max.getOffset() < (peoff.getOffset() + 2): + peoff = off + newoff + if seg_max < peoff + 2: continue - pe_bytes = capa.features.extractors.ghidra.helpers.get_bytes(peoff, 2) + pe_bytes = block_bytez[peoff : peoff + 2] if pe_bytes == pex: - yield off.getOffset(), i + yield off, i def extract_file_embedded_pe() -> Iterator[Tuple[Feature, Address]]: """extract embedded PE features""" - for ea, _ in find_embedded_pe(): - yield Characteristic("embedded pe"), FileOffsetAddress(ea) + + # pre-compute XOR pairs + mz_xor: List[Tuple[bytes, bytes, int]] = [ + ( + capa.features.extractors.helpers.xor_static(b"MZ", i), + capa.features.extractors.helpers.xor_static(b"PE", i), + i, + ) + for i in range(256) + ] + + for block in currentProgram().getMemory().getBlocks(): # type: ignore [name-defined] # noqa: F821 + if not all((block.isLoaded(), block.isInitialized(), "Headers" not in block.getName())): + continue + + for off, _ in find_embedded_pe(capa.features.extractors.ghidra.helpers.get_block_bytes(block), mz_xor): + # add offset back to block start + ea: int = block.getStart().add(off).getOffset() + + yield Characteristic("embedded pe"), FileOffsetAddress(ea) def extract_file_export_names() -> Iterator[Tuple[Feature, Address]]: diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py index 9324e1004..9a3394608 100644 --- a/capa/features/extractors/ghidra/helpers.py +++ b/capa/features/extractors/ghidra/helpers.py @@ -81,12 +81,8 @@ def get_function_blocks(fh: FunctionHandle) -> Iterator[BBHandle]: def get_insn_in_range(bbh: BBHandle) -> Iterator[InsnHandle]: """yield InshHandle for each insn in a given basicblock""" - - bb: ghidra.program.model.block.CodeBlock = bbh.inner - for addr in bb.getAddresses(True): - insn = getInstructionAt(addr) # type: ignore [name-defined] # noqa: F821 - if insn: - yield InsnHandle(address=AbsoluteVirtualAddress(insn.getAddress().getOffset()), inner=insn) + for insn in currentProgram().getListing().getInstructions(bbh.inner, True): # type: ignore [name-defined] # noqa: F821 + yield InsnHandle(address=AbsoluteVirtualAddress(insn.getAddress().getOffset()), inner=insn) def get_file_imports() -> Dict[int, List[str]]: diff --git a/capa/ghidra/capa_ghidra.py b/capa/ghidra/capa_ghidra.py new file mode 100644 index 000000000..99beaffc4 --- /dev/null +++ b/capa/ghidra/capa_ghidra.py @@ -0,0 +1,166 @@ +# Run capa against loaded Ghidra database +# @author Mike Hunhoff (mehunhoff@google.com) +# @category Python 3.capa + +# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: [package root]/LICENSE.txt +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and limitations under the License. +import sys +import logging +import pathlib +import argparse + +import capa +import capa.main +import capa.rules +import capa.ghidra.helpers +import capa.render.default +import capa.features.extractors.ghidra.extractor + +logger = logging.getLogger("capa_ghidra") + + +def run_headless(): + parser = argparse.ArgumentParser(description="The FLARE team's open-source tool to integrate capa with Ghidra.") + + parser.add_argument( + "rules", + type=str, + help="path to rule file or directory", + ) + parser.add_argument( + "-v", "--verbose", action="store_true", help="enable verbose result document (no effect with --json)" + ) + parser.add_argument( + "-vv", "--vverbose", action="store_true", help="enable very verbose result document (no effect with --json)" + ) + parser.add_argument("-d", "--debug", action="store_true", help="enable debugging output on STDERR") + parser.add_argument("-q", "--quiet", action="store_true", help="disable all output but errors") + parser.add_argument("-j", "--json", action="store_true", help="emit JSON instead of text") + + script_args = list(getScriptArgs()) # type: ignore [name-defined] # noqa: F821 + if not script_args or len(script_args) > 1: + script_args = [] + else: + script_args = script_args[0].split() + for idx, arg in enumerate(script_args): + if arg.lower() == "help": + script_args[idx] = "--help" + + args = parser.parse_args(args=script_args) + + if args.quiet: + logging.basicConfig(level=logging.WARNING) + logging.getLogger().setLevel(logging.WARNING) + elif args.debug: + logging.basicConfig(level=logging.DEBUG) + logging.getLogger().setLevel(logging.DEBUG) + else: + logging.basicConfig(level=logging.INFO) + logging.getLogger().setLevel(logging.INFO) + + logger.debug("running in Ghidra headless mode") + + rules_path = pathlib.Path(args.rules) + + logger.debug("rule path: %s", rules_path) + rules = capa.main.get_rules([rules_path]) + + meta = capa.ghidra.helpers.collect_metadata([rules_path]) + extractor = capa.features.extractors.ghidra.extractor.GhidraFeatureExtractor() + + capabilities, counts = capa.main.find_capabilities(rules, extractor, False) + + meta.analysis.feature_counts = counts["feature_counts"] + meta.analysis.library_functions = counts["library_functions"] + meta.analysis.layout = capa.main.compute_layout(rules, extractor, capabilities) + + if capa.main.has_file_limitation(rules, capabilities, is_standalone=True): + logger.info("capa encountered warnings during analysis") + + if args.json: + print(capa.render.json.render(meta, rules, capabilities)) # noqa: T201 + elif args.vverbose: + print(capa.render.vverbose.render(meta, rules, capabilities)) # noqa: T201 + elif args.verbose: + print(capa.render.verbose.render(meta, rules, capabilities)) # noqa: T201 + else: + print(capa.render.default.render(meta, rules, capabilities)) # noqa: T201 + + return 0 + + +def run_ui(): + logging.basicConfig(level=logging.INFO) + logging.getLogger().setLevel(logging.INFO) + + rules_dir: str = "" + try: + selected_dir = askDirectory("Choose capa rules directory", "Ok") # type: ignore [name-defined] # noqa: F821 + if selected_dir: + rules_dir = selected_dir.getPath() + except RuntimeError: + # RuntimeError thrown when user selects "Cancel" + pass + + if not rules_dir: + logger.info("You must choose a capa rules directory before running capa.") + return capa.main.E_MISSING_RULES + + verbose = askChoice( # type: ignore [name-defined] # noqa: F821 + "capa output verbosity", "Choose capa output verbosity", ["default", "verbose", "vverbose"], "default" + ) + + rules_path: pathlib.Path = pathlib.Path(rules_dir) + logger.info("running capa using rules from %s", str(rules_path)) + + rules = capa.main.get_rules([rules_path]) + + meta = capa.ghidra.helpers.collect_metadata([rules_path]) + extractor = capa.features.extractors.ghidra.extractor.GhidraFeatureExtractor() + + capabilities, counts = capa.main.find_capabilities(rules, extractor, True) + + meta.analysis.feature_counts = counts["feature_counts"] + meta.analysis.library_functions = counts["library_functions"] + meta.analysis.layout = capa.main.compute_layout(rules, extractor, capabilities) + + if capa.main.has_file_limitation(rules, capabilities, is_standalone=False): + logger.info("capa encountered warnings during analysis") + + if verbose == "vverbose": + print(capa.render.vverbose.render(meta, rules, capabilities)) # noqa: T201 + elif verbose == "verbose": + print(capa.render.verbose.render(meta, rules, capabilities)) # noqa: T201 + else: + print(capa.render.default.render(meta, rules, capabilities)) # noqa: T201 + + return 0 + + +def main(): + if not capa.ghidra.helpers.is_supported_ghidra_version(): + return capa.main.E_UNSUPPORTED_GHIDRA_VERSION + + if not capa.ghidra.helpers.is_supported_file_type(): + return capa.main.E_INVALID_FILE_TYPE + + if not capa.ghidra.helpers.is_supported_arch_type(): + return capa.main.E_INVALID_FILE_ARCH + + if isRunningHeadless(): # type: ignore [name-defined] # noqa: F821 + return run_headless() + else: + return run_ui() + + +if __name__ == "__main__": + if sys.version_info < (3, 8): + from capa.exceptions import UnsupportedRuntimeError + + raise UnsupportedRuntimeError("This version of capa can only be used with Python 3.8+") + sys.exit(main()) diff --git a/capa/ghidra/helpers.py b/capa/ghidra/helpers.py index 342d4f9ad..b7debc163 100644 --- a/capa/ghidra/helpers.py +++ b/capa/ghidra/helpers.py @@ -78,7 +78,7 @@ def is_running_headless(): def is_supported_file_type(): file_info = currentProgram().getExecutableFormat() # type: ignore [name-defined] # noqa: F821 - if file_info.filetype not in SUPPORTED_FILE_TYPES: + if file_info not in SUPPORTED_FILE_TYPES: logger.error("-" * 80) logger.error(" Input file does not appear to be a supported file type.") logger.error(" ") @@ -92,8 +92,9 @@ def is_supported_file_type(): def is_supported_arch_type(): - file_info = currentProgram().getLanguageID() # type: ignore [name-defined] # noqa: F821 - if "x86" not in file_info or not any(arch in file_info for arch in ["32", "64"]): + lang_id = str(currentProgram().getLanguageID()).lower() # type: ignore [name-defined] # noqa: F821 + + if not all((lang_id.startswith("x86"), any(arch in lang_id for arch in ("32", "64")))): logger.error("-" * 80) logger.error(" Input file does not appear to target a supported architecture.") logger.error(" ") diff --git a/capa/main.py b/capa/main.py index 53f8fa597..b91ca1e26 100644 --- a/capa/main.py +++ b/capa/main.py @@ -97,6 +97,7 @@ E_INVALID_FILE_ARCH = 17 E_INVALID_FILE_OS = 18 E_UNSUPPORTED_IDA_VERSION = 19 +E_UNSUPPORTED_GHIDRA_VERSION = 20 logger = logging.getLogger("capa") diff --git a/scripts/show-features.py b/scripts/show-features.py index 9437caa58..295176a9d 100644 --- a/scripts/show-features.py +++ b/scripts/show-features.py @@ -199,6 +199,21 @@ def ida_main(): return 0 +def ghidra_main(): + import capa.features.extractors.ghidra.extractor + + extractor = capa.features.extractors.ghidra.extractor.GhidraFeatureExtractor() + + for feature, addr in extractor.extract_file_features(): + print(f"file: {format_address(addr)}: {feature}") + + function_handles = tuple(extractor.get_functions()) + + print_features(function_handles, extractor) + + return 0 + + def print_features(functions, extractor: capa.features.extractors.base_extractor.FeatureExtractor): for f in functions: if extractor.is_library_function(f.address): @@ -248,5 +263,7 @@ def print_features(functions, extractor: capa.features.extractors.base_extractor if __name__ == "__main__": if capa.helpers.is_runtime_ida(): ida_main() + elif capa.helpers.is_runtime_ghidra(): + ghidra_main() else: sys.exit(main()) diff --git a/tests/test_ghidra_features.py b/tests/test_ghidra_features.py index 0ea1b1a7c..dc51aef45 100644 --- a/tests/test_ghidra_features.py +++ b/tests/test_ghidra_features.py @@ -10,9 +10,16 @@ """ import sys import logging +from pathlib import Path import pytest -import fixtures + +try: + sys.path.append(str(Path(__file__).parent)) + import fixtures +finally: + sys.path.pop() + logger = logging.getLogger("test_ghidra_features") From fddec33d04d98ebca2c17b45db73ed3332117d28 Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Fri, 25 Aug 2023 19:03:38 -0700 Subject: [PATCH 30/46] ghidra: fix api info caching (#1766) * cache and retrive imports, externs, and fakes in FunctionHandle objects * reduce cache retreival calls * cache in GhidraFeatureExtractor, point fh.ctx to cache * move caching routine to __init__ --- capa/features/extractors/ghidra/basicblock.py | 4 +- capa/features/extractors/ghidra/extractor.py | 13 +++- capa/features/extractors/ghidra/helpers.py | 6 +- capa/features/extractors/ghidra/insn.py | 73 ++++++++++++++----- 4 files changed, 71 insertions(+), 25 deletions(-) diff --git a/capa/features/extractors/ghidra/basicblock.py b/capa/features/extractors/ghidra/basicblock.py index 7811ba0c3..b3271586e 100644 --- a/capa/features/extractors/ghidra/basicblock.py +++ b/capa/features/extractors/ghidra/basicblock.py @@ -137,7 +137,9 @@ def extract_features(fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Featur def main(): features = [] - for fh in capa.features.extractors.ghidra.helpers.get_function_symbols(): + from capa.features.extractors.ghidra.extractor import GhidraFeatureExtractor + + for fh in GhidraFeatureExtractor().get_functions(): for bbh in capa.features.extractors.ghidra.helpers.get_function_blocks(fh): features.extend(list(extract_features(fh, bbh))) diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py index 4034ba50c..f68b5dd05 100644 --- a/capa/features/extractors/ghidra/extractor.py +++ b/capa/features/extractors/ghidra/extractor.py @@ -20,10 +20,15 @@ class GhidraFeatureExtractor(FeatureExtractor): def __init__(self): super().__init__() + import capa.features.extractors.ghidra.helpers as ghidra_helpers + self.global_features: List[Tuple[Feature, Address]] = [] self.global_features.extend(capa.features.extractors.ghidra.file.extract_file_format()) self.global_features.extend(capa.features.extractors.ghidra.global_.extract_os()) self.global_features.extend(capa.features.extractors.ghidra.global_.extract_arch()) + self.imports = ghidra_helpers.get_file_imports() + self.externs = ghidra_helpers.get_file_externs() + self.fakes = ghidra_helpers.map_fake_import_addrs() def get_base_address(self): return AbsoluteVirtualAddress(currentProgram().getImageBase().getOffset()) # type: ignore [name-defined] # noqa: F821 @@ -37,7 +42,13 @@ def extract_file_features(self): def get_functions(self) -> Iterator[FunctionHandle]: import capa.features.extractors.ghidra.helpers as ghidra_helpers - yield from ghidra_helpers.get_function_symbols() + for fhandle in ghidra_helpers.get_function_symbols(): + fh: FunctionHandle = FunctionHandle( + address=fhandle.getEntryPoint().getOffset(), + inner=fhandle, + ctx={"imports_cache": self.imports, "externs_cache": self.externs, "fakes_cache": self.fakes}, + ) + yield fh @staticmethod def get_function(addr: int) -> FunctionHandle: diff --git a/capa/features/extractors/ghidra/helpers.py b/capa/features/extractors/ghidra/helpers.py index 9a3394608..0f405870d 100644 --- a/capa/features/extractors/ghidra/helpers.py +++ b/capa/features/extractors/ghidra/helpers.py @@ -64,11 +64,9 @@ def get_block_bytes(block: ghidra.program.model.mem.MemoryBlock) -> bytes: return get_bytes(block.getStart(), block.getSize()) -def get_function_symbols() -> Iterator[FunctionHandle]: +def get_function_symbols(): """yield all non-external function symbols""" - - for fhandle in currentProgram().getFunctionManager().getFunctionsNoStubs(True): # type: ignore [name-defined] # noqa: F821 - yield FunctionHandle(address=AbsoluteVirtualAddress(fhandle.getEntryPoint().getOffset()), inner=fhandle) + yield from currentProgram().getFunctionManager().getFunctionsNoStubs(True) # type: ignore [name-defined] # noqa: F821 def get_function_blocks(fh: FunctionHandle) -> Iterator[BBHandle]: diff --git a/capa/features/extractors/ghidra/insn.py b/capa/features/extractors/ghidra/insn.py index 41787cc85..2404207ce 100644 --- a/capa/features/extractors/ghidra/insn.py +++ b/capa/features/extractors/ghidra/insn.py @@ -22,15 +22,44 @@ # byte range within the first and returning basic blocks, this helps to reduce FP features SECURITY_COOKIE_BYTES_DELTA = 0x40 -# significantly cut down on runtime by caching api info -imports = capa.features.extractors.ghidra.helpers.get_file_imports() -externs = capa.features.extractors.ghidra.helpers.get_file_externs() -mapped_fake_addrs = capa.features.extractors.ghidra.helpers.map_fake_import_addrs() +def get_imports(ctx: Dict[str, Any]) -> Dict[int, Any]: + """Populate the import cache for this context""" + if "imports_cache" not in ctx: + ctx["imports_cache"] = capa.features.extractors.ghidra.helpers.get_file_imports() + return ctx["imports_cache"] -def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: - """check instruction for API call""" + +def get_externs(ctx: Dict[str, Any]) -> Dict[int, Any]: + """Populate the externs cache for this context""" + if "externs_cache" not in ctx: + ctx["externs_cache"] = capa.features.extractors.ghidra.helpers.get_file_externs() + return ctx["externs_cache"] + + +def get_fakes(ctx: Dict[str, Any]) -> Dict[int, Any]: + """Populate the fake import addrs cache for this context""" + if "fakes_cache" not in ctx: + ctx["fakes_cache"] = capa.features.extractors.ghidra.helpers.map_fake_import_addrs() + return ctx["fakes_cache"] + + +def check_for_api_call( + insn, externs: Dict[int, Any], fakes: Dict[int, Any], imports: Dict[int, Any], imp_or_ex: bool +) -> Iterator[Any]: + """check instruction for API call + + params: + externs - external library functions cache + fakes - mapped fake import addresses cache + imports - imported functions cache + imp_or_ex - flag to check imports or externs + + yields: + matched api calls + """ info = () + funcs = imports if imp_or_ex else externs # assume only CALLs or JMPs are passed ref_type = insn.getOperandType(0) @@ -42,7 +71,7 @@ def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: # If it's an address in a register, check the mapped fake addrs # since they're dereferenced to their fake addrs op_ref = insn.getAddress(0).getOffset() - ref = mapped_fake_addrs.get(op_ref) # obtain the real addr + ref = fakes.get(op_ref) # obtain the real addr if not ref: return else: @@ -50,9 +79,7 @@ def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: elif ref_type in (addr_data, addr_code) or (OperandType.isIndirect(ref_type) and OperandType.isAddress(ref_type)): # we must dereference and check if the addr is a pointer to an api function addr_ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn) - if not capa.features.extractors.ghidra.helpers.check_addr_for_api( - addr_ref, mapped_fake_addrs, imports, externs - ): + if not capa.features.extractors.ghidra.helpers.check_addr_for_api(addr_ref, fakes, imports, externs): return ref = addr_ref.getOffset() elif ref_type == OperandType.DYNAMIC | OperandType.ADDRESS or ref_type == OperandType.DYNAMIC: @@ -65,9 +92,7 @@ def check_for_api_call(insn, funcs: Dict[int, Any]) -> Iterator[Any]: # that had no address reference. # This check is faster than checking for (indirect and not address) return - if not capa.features.extractors.ghidra.helpers.check_addr_for_api( - addr_ref, mapped_fake_addrs, imports, externs - ): + if not capa.features.extractors.ghidra.helpers.check_addr_for_api(addr_ref, fakes, imports, externs): return ref = addr_ref.getOffset() @@ -88,13 +113,17 @@ def extract_insn_api_features(fh: FunctionHandle, bb: BBHandle, ih: InsnHandle) if not capa.features.extractors.ghidra.helpers.is_call_or_jmp(insn): return + externs = get_externs(fh.ctx) + fakes = get_fakes(fh.ctx) + imports = get_imports(fh.ctx) + # check calls to imported functions - for api in check_for_api_call(insn, imports): + for api in check_for_api_call(insn, externs, fakes, imports, True): for imp in api: yield API(imp), ih.address # check calls to extern functions - for api in check_for_api_call(insn, externs): + for api in check_for_api_call(insn, externs, fakes, imports, False): for ext in api: yield API(ext), ih.address @@ -306,6 +335,10 @@ def extract_insn_cross_section_cflow( if not capa.features.extractors.ghidra.helpers.is_call_or_jmp(insn): return + externs = get_externs(fh.ctx) + fakes = get_fakes(fh.ctx) + imports = get_imports(fh.ctx) + # OperandType to dereference addr_data = OperandType.ADDRESS | OperandType.DATA addr_code = OperandType.ADDRESS | OperandType.CODE @@ -317,14 +350,14 @@ def extract_insn_cross_section_cflow( if OperandType.isRegister(ref_type): if OperandType.isAddress(ref_type): ref = insn.getAddress(0) # Ghidra dereferences REG | ADDR - if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, mapped_fake_addrs, imports, externs): + if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, fakes, imports, externs): return else: return elif ref_type in (addr_data, addr_code) or (OperandType.isIndirect(ref_type) and OperandType.isAddress(ref_type)): # we must dereference and check if the addr is a pointer to an api function ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn) - if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, mapped_fake_addrs, imports, externs): + if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, fakes, imports, externs): return elif ref_type == OperandType.DYNAMIC | OperandType.ADDRESS or ref_type == OperandType.DYNAMIC: return # cannot resolve dynamics statically @@ -336,7 +369,7 @@ def extract_insn_cross_section_cflow( # that had no address reference. # This check is faster than checking for (indirect and not address) return - if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, mapped_fake_addrs, imports, externs): + if capa.features.extractors.ghidra.helpers.check_addr_for_api(ref, fakes, imports, externs): return this_mem_block = getMemoryBlock(insn.getAddress()) # type: ignore [name-defined] # noqa: F821 @@ -472,7 +505,9 @@ def extract_features( def main(): """ """ features = [] - for fh in capa.features.extractors.ghidra.helpers.get_function_symbols(): + from capa.features.extractors.ghidra.extractor import GhidraFeatureExtractor + + for fh in GhidraFeatureExtractor().get_functions(): for bb in capa.features.extractors.ghidra.helpers.get_function_blocks(fh): for insn in capa.features.extractors.ghidra.helpers.get_insn_in_range(bb): features.extend(list(extract_features(fh, bb, insn))) From 9cea7346b23e8c32faa60f45a9c55b2e08309717 Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Sun, 27 Aug 2023 19:21:36 -0700 Subject: [PATCH 31/46] ghidra: documentation (#1759) * Implement ghidra documentation --- README.md | 2 + capa/ghidra/README.md | 163 +++++++++++++++++++++++ doc/img/ghidra_backend_logo.png | Bin 0 -> 62542 bytes doc/img/ghidra_console_output.png | Bin 0 -> 79236 bytes doc/img/ghidra_script_mngr_output.png | Bin 0 -> 110986 bytes doc/img/ghidra_script_mngr_rules.png | Bin 0 -> 112394 bytes doc/img/ghidra_script_mngr_verbosity.png | Bin 0 -> 80857 bytes 7 files changed, 165 insertions(+) create mode 100644 capa/ghidra/README.md create mode 100755 doc/img/ghidra_backend_logo.png create mode 100755 doc/img/ghidra_console_output.png create mode 100755 doc/img/ghidra_script_mngr_output.png create mode 100755 doc/img/ghidra_script_mngr_rules.png create mode 100755 doc/img/ghidra_script_mngr_verbosity.png diff --git a/README.md b/README.md index 9a42cdf1d..80a5248e9 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,8 @@ capa explorer helps you identify interesting areas of a program and build new ca ![capa + IDA Pro integration](https://github.com/mandiant/capa/blob/master/doc/img/explorer_expanded.png) +If you use Ghidra, you can use the Python 3 [Ghidra feature extractor](/capa/ghidra/). This integration enables capa to extract features directly from your Ghidra database, which can help you identify capabilities in programs that you analyze using Ghidra. + # further information ## capa - [Installation](https://github.com/mandiant/capa/blob/master/doc/installation.md) diff --git a/capa/ghidra/README.md b/capa/ghidra/README.md new file mode 100644 index 000000000..ad7221733 --- /dev/null +++ b/capa/ghidra/README.md @@ -0,0 +1,163 @@ +
+ +
+ +The Ghidra feature extractor is an application of the FLARE team's open-source project, Ghidrathon, to integrate capa with Ghidra using Python 3. capa is a framework that uses a well-defined collection of rules to identify capabilities in a program. You can run capa against a PE file, ELF file, or shellcode and it tells you what it thinks the program can do. For example, it might suggest that the program is a backdoor, can install services, or relies on HTTP to communicate. The Ghidra feature extractor can be used to run capa analysis on your Ghidra databases without needing access to the original binary file. + +## Getting Started + +### Installation + +| Dependency | Version | Source | +|------------|---------|--------| +| Ghidrathon | `>= 3.0.0` | https://github.com/mandiant/Ghidrathon | +| Python | `>= 3.8` | https://www.python.org/downloads | +| Ghidra | `>= 10.2` | https://ghidra-sre.org | + +In order to run capa using the Ghidra feature extractor, you must install capa as a library and obtain the official capa rules that match the version you have installed. You can do this by completing the following steps using the Python 3 interpreter that you have configured for your Ghidrathon installation: + +1. Install capa and its dependencies from PyPI: +```bash +$ pip install flare-capa +``` + +2. Download and extract the [official capa rules](https://github.com/mandiant/capa-rules/releases) that match the version you have installed + 1. Use the following command to view the version of capa you have installed: +```bash +$ pip show flare-capa +OR +$ capa --version +``` + +3. Copy `capa_ghidra.py`, found [here](/capa/ghidra/capa_ghidra.py), to your Ghidra user scripts directory OR manually add `` to the Ghidra Script Manager. + 1. This entrypoint script is located in `capa_install_dir/capa/ghidra/` + +Once Ghidrathon is configured, you may now invoke capa from within Ghidra in three different ways. Each method suits different use cases of capa, and they include Ghidra's `headlessAnalyzer`, `Scripting Console`, and `Script Manger`. + +## Running capa with the Ghidra feature extractor + +### Ghidra's Headless Analyzer + +To invoke capa headlessly (i.e. without the Ghidra user interface), we must call the `analyzeHeadless` script provided in your `$GHIDRA_INSTALL_DIR/support` and point it towards capa's `capa_ghidra.py`. One thing to note is that capa runs as a `PostScript`, as in post-analysis script, so we need to provide `analyzeHeadless` with the path and script to run against our project. The preferred method for the Ghidra feature extractor is the entrypoint script, `/capa/ghidra/capa_ghidra.py`. Additional capa command line arguments must be provided in a single, space-delimited string i.e. `"/path/to/rules -v"`. To display the help & usage statement, the keyword `help` must be used instead of the typical `-h or --help`. + +The syntax is as so: +```bash +./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/gpr_dir/ gpr_name -process sample_name.exe_ -ScriptPath /path/to/capa_ghidra.py/ -PostScript capa_ghidra.py "/path/to/capa/rules/" +``` +> **Note:** You may add the `$GHIDRA_INSTALL_DIR/support` to your `$PATH` in order to call `analyzeHeadless` as a standalone program. + +If you do not have an existing ghidra project, you may also create one with the Headless Analyzer via the `-Import` flag. Post scripts may also be ran in the same invocation. + +The syntax to both import a new file and run capa against it is: +```bash +./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/gpr_dir/ gpr_name -Import /path/to/sample_name.exe_ -ScriptPath /path/to/capa_install/capa/ghidra -PostScript capa_ghidra.py "/path/to/rules/" +``` +> **Note:** The `/path/to/gpr_dir/` must exist before importing a new project into it. + +**Example Output - very verbose flag:** +``` +$ analyzeHeadless /home/wampus test -process Practical\ Malware\ Analysis\ Lab\ 01-01.dll_ -PostScript capa_ghidra.py "/home/wampus/capa/rules -vv" +[...] +INFO REPORT: Analysis succeeded for file: /Practical Malware Analysis Lab 01-01.dll_ (HeadlessAnalyzer) +INFO SCRIPT: /ghidra_scripts/capa_ghidra.py (HeadlessAnalyzer) +md5 290934c61de9176ad682ffdd65f0a669 +sha1 +sha256 f50e42c8dfaab649bde0398867e930b86c2a599e8db83b8260393082268f2dba +path /home/spring/Documents/capa/tests/data/Practical Malware Analysis Lab 01-01.dll_ +timestamp 2023-08-25 15:40:39.990986 +capa version 6.0.0 +os windows +format Portable Executable (PE) +arch x86 +extractor ghidra +base address global +rules /home/spring/Documents/capa/rules +function count 5 +library function count 0 +total feature count 376 + +contain loop (3 matches, only showing first match of library rule) +author moritz.raabe@mandiant.com +scope function +function @ 0x10001010 + or: + characteristic: loop @ 0x10001010 + +delay execution (2 matches, only showing first match of library rule) +author michael.hunhoff@mandiant.com, @ramen0x3f +scope basic block +mbc Anti-Behavioral Analysis::Dynamic Analysis Evasion::Delayed Execution [B0003.003] +references https://docs.microsoft.com/en-us/windows/win32/sync/wait-functions, https://github.com/LordNoteworthy/al-khaser/blob/master/al-khaser/TimingAttacks/timing.cpp +basic block @ 0x10001154 in function 0x10001010 + or: + and: + os: windows + or: + api: kernel32.Sleep @ 0x10001159 + +check mutex +namespace host-interaction/mutex +author moritz.raabe@mandiant.com, anushka.virgaonkar@mandiant.com +scope basic block +mbc Process::Check Mutex [C0043] +basic block @ 0x1000102E in function 0x10001010 + and: + or: + api: kernel32.OpenMutex @ 0x10001059 + +create mutex +namespace host-interaction/mutex +author moritz.raabe@mandiant.com, michael.hunhoff@mandiant.com +scope function +mbc Process::Create Mutex [C0042] +function @ 0x10001010 + or: + api: kernel32.CreateMutex @ 0x1000106E + +create process on Windows +namespace host-interaction/process/create +author moritz.raabe@mandiant.com +scope basic block +mbc Process::Create Process [C0017] +basic block @ 0x10001179 in function 0x10001010 + or: + api: kernel32.CreateProcess @ 0x100011AF + + + +Script /ghidra_scripts/capa_ghidra.py called exit with code 0 +INFO ANALYZING changes made by post scripts: /Practical Malware Analysis Lab 01-01.dll_ (HeadlessAnalyzer) + +[...] +``` + +### Ghidra's Script Manager + +To invoke capa from the `Ghidra Script Manager`, open your Ghidra Project's Code Browser and open the `Script Manager` window by navigating to `Window -> Script Manager`. Select `capa_ghidra.py` and run the script. capa will then prompt you to choose a `rules` directory and specify the output verbosity level. +> **Note:** In order for the Script Manager to recognize `capa_ghidra.py` you must either copy it to your Ghidra user scripts directory or update the Script Manager search path to include directory that contains it. + + +
+ + + +
+ +### Ghidrathon's Script Console + +To invoke capa from Ghidrathon's Script Console, open your Ghidra project's Code Browser and open the `Ghidrathon` window by navigating to `Window -> Ghidrathon`. + +You must import capa into the console and run it via: + +```python3 +>>> import capa +>>> from capa.ghidra import capa_ghidra +>>> capa_ghidra.main() +``` + +Similarly to the Ghidra Script Manager, you will be prompted to choose a capa rules directory and specify output verbosity: + +
+ +
+ diff --git a/doc/img/ghidra_backend_logo.png b/doc/img/ghidra_backend_logo.png new file mode 100755 index 0000000000000000000000000000000000000000..61199d2529042ee7bd864343645cec20cd91bc65 GIT binary patch literal 62542 zcmV*RKwiIzP)8LsPT=yj){3W3kIkP1~%2EWrUM zo81iy`bdKY4VDKBFqS-5fM0vKH14?u$I(y#E<*0;@A_z8H1uD>y4LG?iYvRKZ0v{; z(;(?-I3XxG9uq~6>G2|ClMZuUnM%mS1!k)bqowlK59X`CIyN^qbPhu?Z|Uv$pD|r~ zhk`yKgiuPkCD(g)y6XJZ%M;U|U#>YfXmAN(bT!BOn@#IhOK9sXDcTKPOPYu%0#|{f zl(K~ou26VND1Y&zQaHYst@^6ucudWftKZ*0J39;%X($Mn91R8FBIDk5T@Us|!~b2A z;xa=B-g#9kTUx@zLjtKulnPw@%2(K)pz8SKZI_XuBG0~@Wln=RT~YBBW!Ia0alZI# z&yP*~!E%5O4H{fr zBoc}A)~4uhw1mtX3?W)|DKfec&6<>^R=dAErSNO_w-f?R2!uTO60dxPrxaD+E4ZFN zf)ItNiu2gZbA>;j$Y#fY>T1oc!P?PK0M>}!WO87AQ}j2ZhQ3jgA^}(eqyklO{h3+Y z{qaz~^tp*__R#A+=5>87?N=p}|DUJCtvyX9Z@MhS6`he276BoSeXf+E>cDi-W@MYaLE%6hdVcSYpTJ6^L6yzM2 zuqH|A8mWZAx~33anJ_U8DyBuq4rF+F)@Ee9z--ZFT0lh!szRM0;eDm3cs`EuXB|(? zR6I3Zbe)m$QuP}zPtN@P>YjlHt3g8nSYI@RMgJ**j)4Wq4Exq<*&IJoVyy_7g8p%N)-{E=sw+lI+{7{#7Y~uM!S?aS zi#TIJEU#BlR2(P+j(~X&4uxPZf~-)-2mx)$-!6fIUiN(QwzK!ueCdx4PR)J=sI0=d zXs`-26oA!3ynAEcS2C7)w}Olz1co69%VQ;f+4pfAg$E1fJRt;1DQsV{V=DXDxb6P^ z+?@YUke#o8?xD;3KNHjShoY92e&6;Mw)MpDJs(x{sO*`ga<~YNVyQQ9VPF!_1+rNq zvY{EHJ%TM^_ses<@?wb@!(+_w@PL_$y?@tC;pg{HPd~c!7}s~DySJy)e-7MzWoIn$ z&^2v@%wXKguVofGi*8Kp83Lm{>jkT|6G)gxmTBT)&HTsMs&t4?(a*{)Dj4LYe|@&s)93KqO@-sf5rn(q1@n}R+=Cy zVXrSJpi@=?Pbh{$E;*qVvVjzV70?#~+x3{N*zC`jnQ|6G0(2?R5qVRn$5HAjCBzX! zkW-M;ls8>)m^GBjX}MhKNJBxmU}z`+tHir6>;Ic{$oO!?lw8#jqbn0$@XaqJUs23Y z*}Ph@nJ?NDY>(l&D$^wwAp_rD&T-kFFTFTZalUw8(jkSqVM zJ%#dT=UlgVM=Ej0rl!cpZC_n^O;@bxp=;W(46tWxyzvs%u^irL&FbI*8VFNR74V!d zm{JBahR2lQQ4w$?TmH)P)AJu6&F5!U>i1~SV2v@iwYR>vBVvBMHyXM|2%#w-nj<>h zDU0@~Nmt6`vbHE8Gq`E%3cWjP;}vY2Bl9>DfkrP3aCJdNz`QS*1%{M?Cl>d zIpwLMhbr5ipD%j;;at^u-tqi{6~FpYX>@L457?`Fnj4&sh61n(ylH*s2YVxt-!r7_ zf9F-LyrD0;u&Yx}OcWdr&Q@@Ig&_k)V5m?o4kn^e zQwlnhCcnD96$&o-CnmsAf#5&WUs=_Z0UtzIFr3ubJ0mFod8CsOG^;n0IW;&>1#yW-H`>Fj|{aup2pM914Vhst9%{Q|Qb{cR|S*E>)j@ZYKY} zBeSzFpYspUpuu@UCXQ=UK&!z17%v2qII8#7K=rJ_Xrj8{g zDO0B_5<-`Y7DuCY)0&z<2P`GfLdRMyElX0ZE}9n0zK?R$Lf)b4`jx8kCk!cPfJ)AF zkIa;vr%Sf~*p9KW-85o<){KS%unK(O@_}zyQoij?8`JX6O{rjae58bDdtfigyfHO2 zQv*|Cq(jIh)&bx18O=EiWgYg86?pt;jzh-lP9vH(N!`mZ?q@@#kwd;u3{k5D5N*H3hoBqRS}r>E3D$5Ahg`nktm7|PC_@yTs)Rx}iV73SK`%*Jb) z(_hnt*!;I!4M^*cD`p9xqLm**jKX z_gE261(t)~k7njFv(;j-tC<{jtJ@k;eGyGN&Yoy#d` z(BN#iyfuB}#-{kET0`a=ln&^;9+_Kkn+YA%l1!eZ z_sa+{j(&{bhhWz~r@?N!!qHNN@v2K-*rYXN5;rswhK^s`Y1d5g9j{DI{@`Sv>&s*|UEdu4>xizsL6=hV)S}Zt_fa_o@>ro?r~b-5wP@}?Uii-#9!I3h{Ew%edR%pa^&)S(RH{BdK9pt0a306^%L4VdQeuDJ z@pgXuz|iN;_)8kRCJhB(g}JUXp1G#E?JJfL*S^~oO??h$cGeXL6-4&Rm_Rg3td2CH z^|6J;BVSQW?3^HTq>R#6{wJN5@VsYGR)Uh|(AyQ_PNgUxEu+NQyB_L0n-`Se5IR-q zE>!~5b2GVjy*xSd^(7yPZ*On?51UibKT4QJQ`Ph7h!{MuHA6aP5I1!Irt&slduf`( zb5-VT=dZs0>XDD0<0)v+;I#C$MB1-RH-EX!vhMU$P~hWjS2S~dPmDxFE~MsGhVoR8 z%;C>@P*tb3oC$*M@F4|zm3h+l%orZK{R-pdDw&W;lc8g261Nukw^^6mFp#3FH%fEV zJgvY#nUG%^x3n~^_yl+6$ynmzTu47QbuiRo%)^q6&ECl}PaMrtvRw~&BJa9C8O_;$ z|J3;Sp4a>V8oVwV3cxDxk*$ND(uCOl9$(zG@uV62uahOgc}BA&bX7Y>TM#f*ovu>& z?(nK80D@o#QeT9wHf%Z_bxZyG^0wHYG1gZcMO0X@eam~gS zdfGz>Yw>e+fnOK)$L#o*2>E(8k3Z+3JP^JLIt-ivWld0(FjR|KC@-;GgoVNjIjnDw z(AJrxJtnDy0|kEXNSW{LpP}sglx>xFQ7<0MmHzgT!y|uvW+P~DJPifl%#efav5e`3 zle$hj5EWAC!bABYxbuYX+e(V8FT5$ID(90Sm0X`_dUwRoZn_Eap4)A()VcTE6>gvi zX#EC&|g}kqn>Tx4&|th6j2VSs#;9ltt%=^2lhHxs<_nC z5|4LVET!OPi3)+x5`=}KEd@=|XOCsDzvPgs1{(s~^Iw^%+CMxzQ~2+@XJHe#4Y1`OV=-pX!0^s%5ES5#DJ(Sr7n+`dP>;%mjO<%S@CjfB)_MN8i89 zLvL`2a^FDLANR+jpHxaQmo>=z#eZc*;{t_hi4|K z0EY{uzxdvP;ZLl<@Ecr0yls8&=euK}pYxSsdqzW;Z1qqsMqa=I1`GmL-;Q( zR8*C(9q@1Y`Z4dH(;%-0H3uA}n5{TZjF!uP{>0IVe>~?2Tmm!{fEsV#(D%Nip}!Z@ z{b60xZthDgG}fr+y@ssCXxTdTI`_w8dyA*`_(<0t9}53Iy6iXH>&d&nkf^%?_7S)m zmSzU{o}xLT^U&3;tc&PW_RLZ~SX}(z$&TkLWV?>lk>DHCWuBf3iYo1$%m2zxhR6SM zwdU2};^KkJ`o7Q}wm#t36w)^gBJgojw&|Ad*VcxaB`0#`VMGm*1AczE0T-oNaOS|780#hvSt+`B1F zA|kP8Y~20xln)gV{@Gjm>KQSoGoSaT75$etF9i50KZvSds4FmDq&ic?AFqkmQ=}L! zCnL3V-a2)mUl;gG1$Mm`LA~jbs}zo}aFzt}dcH!djoA{-h3%7Hy&lmFT<#2Y`s>tX3aSkfHwEjsUA-%QKU+!?1I*5eDFGT~VP zu7Hy5KJ%qL2XExWb)-Rqlk&E~zCY=TTECHZTyE}3P;Y=$ovu>ZF^ZF|H`zGzW7n_I zpLnM>{Yy8`?VDTayCQQ;Djh)S)g09$bEuq$s?^q=RSFI+2-x8p3-Jo|J|8Y8R`pq$ ztph;^R8O5~RrQy=<|;+r@tC(AW~wfxCg_iaX$zSrJ=MNa*q(ZFtW^HX?;RTX(z(s> z;^LB*KG&pD$!oh?zI{`F{FVo=%q(io<0ZVIES0GWel^I&KV{lW?Y>h&AY>3kqlE;% zDKX=rprT*Q2qMy>+JZl>vU@hD?cJ~foE8DcG!6oYH~ZWv75=z;R_D(H_9($FT{2wD zFgTnq{^i35M}B1)hu+{K<=%BYzug}X{b7CQfB)8IECb5>@|2&O4s!a>^1iN{{&%Xy z>-~6og~JWkW)|v!)cb~1hVnT3W^m_y@K?sf|5}VF!OmJ8j|mgz@$pU(BqS9`?Zg2F zL5soPz6joTJoOgpwy&^#AE%blP`4ZyLJ-w8bWJX}6DqFz?2%&i3y&Ng`SWv`P}16v0JXQMeTazE63y02CIh z(d!W293!+jjn*57{kh<7Z|DH0L;+z1T|nJNpPKRTm4DWYtPZ4sjH3lz2!Y;M{at-A>$d@}>xyyz)@DpiQQkF6>6t9V1e~K%e@Jms;U5-? zs}qWKw{@c>41CXD*s$b(Iss)BxB*_zdbI+0zz9L-!RZKurKHnZ6f-RmgZ8LNGGWr2 zG-!^V+`>_3x@a?$b;#yy#)~#nrNu%j)v8a~_c5GW(;~@2$5aT`jk4=;Fjr#McIc0V zX%3lJuTSb%ue)OKXLrqK|HH1~sr@T(8ZHv+g19*I z$oASjuj=lDr8i*xI#*EMTcEtBfC$&L^M>$$O+27WC`NFYQU+;&b1-Qtpj{|>aVS*< z2Q7ss1Y4S-U(P%6Z3n0G`<7|w4K5}uXH7>j;d2obJF`x_OP@}61BdkW|5(yIs1 z&7NdY=&@{iwlp)aE=cXGyCy3yPY2C{3<2S@Shtp$N=BonIm|8bFzJN05IkKkeO%{w z^Z!z}YyIE4noPP=)-kWwO928C4OrV-kbO#Su2>HHn%`~?jzI<_VgUowU4?M#~7vnfS~ zCdus@!8`0hczM>183cvnmgXSPuY;Z*3mmA9mV@3K2fU!b&q_1^I}3CT?rL%{tvJ{Y z=nQ(lWscbxc-6$b^uok&FiE1B3111;t>xXfrzHFjKK9I380| zCFb)!W75ZvlCZ9ku?&2rn6uq?jFl>Hxw5n6uIWPcKMm({vnzLI&QC6R1wbiL1`6)1 zo$}|^>fT7_$31(&pn#ZyUK~QpP)H*Okj|SfOVQ#%?)ee?VQ*R1jr#6?1cJ1`+Uxyk#f{gsVx$b5IR|(D zJe9*maMXFR<6nyMzxLU8MjHS(bhSUYJrn<`6oPx!H*r^Il+sIMLG`?Ite98l_>@-& zg#VSdbrRPkmHqQLN9J*7{WS^hTUJhS^NPAzv=#tZ4+N~&ED$;f3q(W%Qw2(bsVyi8 znA%CRvHXf6@A(Vuh>sr5vv5GPxEgeadhx(F~o}a)U@s?c>kNPmKbUdLLNW%?xcVo;|DLgZZbFheCIeo{# z3kGqjhX@|B_Rwk%S(~#D$^nW#YF^>a+PE`SoXHB#WCeG!gfp6_I-JL!s^U&o@T&@G z3M@k-oz!WK8T56=xxO>ZmRJaFy3CA#lCOy9dVAc^ZfR>y-QFILi34-F=hp5dtvna{ zWpvJbbYowC!m@th=WPBG=Frd#0vNSOm7UwM7S# z){VN5gJDhffr@%Q4DM}rHTcW>(ZUdFQS^?*;jp@Wv4p&fsvMm8k9Fv-DbtDK4HZAr@s5K9JZluU} z4`dnlTr43$aM1SDBZrEm&pvi!bk|x=Yo)m4uBbt&iY{+#XA$x^TmI`{x zWjp8l(A5Az3vJqD~0VV`coEHbtPzv zYNTTZ9ZLd?L{wV{ILa11o;Z-@$3t04w$G75`E%bpIQ$E1Fs%mX$eY%6|5;xm@(B-k zuLql)mD?Z)0W+N;y3^ssK);6YKPT#CiN|U}e@Yq0bRS%brUYT3F#Q5a8KSG(LbSv% z!v^EoGJ8rkuTGa#(NVjP<||+N-l3zPTHV>K3>Wkj_8!pe4Lvu-b^V5|ZLxQ@#mp$@p1001BWNkln*sy}yX z0c?#_LBIpm%NP9f(@S`!+X6e(ARL$)3J+c%dQ`fbaQuIS04kg6-qkC&p}O zrgls*31I<-!s)V_D&rmk|-c_DbgR@|;J=W403%$<+wkc@#0->_v@j+rq z8Sw^ZMSbUg&=ZuESjclPX%2H5*tHj`0$k%*+2HBHFRTFy<)9c7_>)sQ&Z|OcaaUfY z=@>fTNvRLSBfoCHn;TDPt(YG^-q>$>D`*Sl}2DwJNFqdJpC z78G8+^`*zDyZ6Dd6{u>}r#!b-PrJb-Nw~JcYf7+DI5gEwzOUz!5TJB{szUkYEY4V- zPN~xx)|st(M0NdL*LAjB`Sj?CDTNKrFM6!R`%NiZHK5mDS<`=m!g9{VQhZqnO&e``GsO{q1d7n1jq02MKg+0Q$ruW68|Ltj}-ny)V zZm{h1#X|ql1+G&t=)C6J8=OZ>`9U8ACv3A<1Zmx2T@V85i@W12-rEU7C#GvlS_=C; zW!E2YJXM%=oM(oI$9IlFsrL4-*FTrZWa8^1@(sPw=o|W@)`n-`f>Z!57;*QW?(T4B zd*su@PcBgczmQGVTL|TCen}ota z23W}ne$j#l#fry#F{t=kusw>lPs#O|D?8))ih3MDK5N_i^0vEowpw~>espf~Vk+`= z!B_x7Nv*#t7P`4JY*K!1G7$dfNe8S37YCYx0Zoze&)wv!fT#)rj>5iANCm4#OUV3X z;78{?*am0JAXxjs-3*!yBGT5DG^7kk;e-rBW~8UJZAeCc%@&wxe40IRS}$UQ^9v1V zQhhYCc}yMfqj$vH*yPK!k&aLS{UK zh?!_HlTa-%JRURYPFZa03F>;}Z8tSraBiC@dbiCNZGLh%`=f-ZZST0O_bp}5-8)kn z{npO01vkM3#Ra1PD1?c?s16l^QjQnQ$QxX$_ym~*hkR&qB{|(Et7C4ArGM)c^1r#( ztmh#oTuIjS zXf}-pfQACF0`w-6shgW)-%eP@O`d|J5?rYiElLnNZqYE8JU41vM?-<`1@4>GUSsNU zBLIoomp9@MR)D&4aJ*trs~KFLFCb(A5fNx1K`AD%;xUMs#Czi;+rxCHL)_%}Oy%u+ z_Dz=W`Tl{q^$&*oI_xq}e(T7QLu)dxv*3bh2Yh{JMrxY4=}P5nP|BzK;?)2dv2iAMg;zLvIk+Ky{F2q&M z?(Zq0K16*834!@qU$TN|z+nS+8emIk_kwHa42#$`I2-Eih->YKl?$q(P&tJ=UB#U! zQ#~?|KW{_TClb|Z&R7h#hPa|Vx~(f7esDBbuB>lL_{CUuESqID%150O7mNb1zInES z-PE(i)9(s9js1Uv3x_f=DI}J!;R`5giin{#@1C0f$F&~Y#l+hN`~IXQZ2rdzinsW1 zYgJ$onE8cL!T&vYxqmCuO>OAR5iWVmH5nX;>KLXZY_DzDUp)?GMpJxC6a3JCkf!ML z1RjAh(9i`|iMm2ie<;9KxHC4+(Gr!HvXuAD1A?ZM#rn=LZ{D1_C8V?u>cvR&U^h(9cfG8svLn09%Jn}jin(UaInEkUX=l?F@ zLSS=COZz|~^hZ*YnX8oGUR&VR%Jta(ZLHq0oUafPS6_kWqbp+7m3z7o%OL$4Z)4E_rgRp>@e*rDr7ZWvwKuCem1fC(N z`cR&zPfg1CRzYdyw`fg3uT|Fk(| z-YbE3IuKC=)!sbCzTT~T`3)atXaCLY?7x{uueq12<34+udU&|+HlFF+j91R{!j8W~ zGa~G-me{YGB%3sn_S&QZ2%y~$3Y<*{K^2$~@QMsxi>M$@p|J$6F7;}I1py-pUR1jK zD!M#`#@?c2&$P?fzIjZk=uB7~&f3=|P5rHXP4P{drN2CxFP~T0Kj&=_;C<`62g91U zI%yi$b%u?*HnqpD?#hH|4QaGYj^gg7(X^+*1wj~S$7NjTXiAW9B}Ky{VrX{&f3U{G zyBN?yn!MQs22muG09Szza~XqgUUfglU2kN5HV424e45e;7%eOuAk}vThud%Czdrs| z07TCqpKCYhu{g z((Ey$8%EKC5SQ2AH}3099dZGeUQJMzTFeNE4}>-Co@OKT$B!Ht`ShAi;yBJb1>o)d zof}Qlc=KQ~{Ltm?(d)Z1VS1AWaZ_Jt`cu`rDeM^u@~j#yk;|)d%#}HF<$6g*`B#NX6Rc0uJHtxr+B%4E4#a|;z&z3#VfC8Ybr!fD#Qy1 zCfQe!Fj`=&ym$;d-b~M1Kh9L9iDK~0bISh|%qPtYf7*&M4pueuU&y#pBVXw4;| z1Eav#HF$%BD_rRG7C+NqWpIHx2?q?{8CK4>g%W#9Qn^y74ItK`7%&loLOD&QFH#{D zv~?MjfCz5xZQ<_4gbFNO^m+xLul&;2!$yL!BZTXnxz!ZP&i5Cg=a-b zwDu9+bPN8(KAt;zm>J*Y>8eXtTa?zyDh3GFCAkO$e$t1cgrh=XAQplFM+A&&po<`Q z@Vr^jFG3_BeP~xgo0lqlSn{+B<4W-IykkFcFjxHgoag;$&i9`vN_LkuHBr)(%ImaM zG(lA=;+`N9Hnyh2)*D@E?3gK)Cf0IJYks}lzpl0I=C1a4zvZ&#zxtVNt?$3%vQ%q- zI;hH|YeAiVRRzD~0upJ6;A*dcGg=N(HX1ZIkEzE24Eu`)x03WJNic-8c1_Oy?b?m* z!e@Od`LULec|}SIuJRyMf|u5Br|H%kxqE$rSEkB5{M=zC{_XQrp8GC@6U4$XJS%d- zu{dFiERc&Vv_+t**ihWS;pIx5gwG_cje_l1EZFsTW$EM@};pa2X> zP%?-cIPc857ZHXCVlM`K(cLA)gLB|d;_tVVk^krYNB8ZU%OBo5lYRb$skujYPR@Q+ zY2t^r5;LYDyF4i}6&ciai0E2JTgdo;uj#K&7D{{8YCdbG0K9P^m3;d^@B8l_X!+xZ zu5JDJjRWy?I;Nw!;7nDpj}$2Eo}~EHEam6tsJxP;{L&ni1M>?>vF?1O;Ra}M-XnmD zfGH$y?PAsOnbkp{;z={|_lI)1{MwH4f+fB&o&3F~kdYZw(Cx#}z*e4Ge;tL6US63h z^UVVVG`mD@-%}Kx{XT`A|4OA&KmcZI|49$3#WPsxPCVsdzxWg0zHuuXN+W?#UX2H|Xy@eYXXByJd_>oqG(ndTLKvDfx}%|=Nk+o4L-Y9` zary@KE5e#603X@1{*Jr)TR#21YubMOhW=Q0T$r3=DXpDI>%iXQc>fW;(R3B{lQh zbL`T0r8yK_N(W+?(YOI_d}f0frOHC@WWUo8sv1%X~72qnt{ z5`-xbQGp(nkkk-qfk;ZUc7<$a;US_LA}JAJ4b1?h*GgjMRd6hiKrdA_WdUd?2xo>M zXf>QwioB@R0{|T1la~kjIZ>{c?!=z3cj=OT50bNaz}PzCfiTy7KnvolqZKMJo|mVTyg0g zOtZD*u6VSa5a26^=+({O`8dNBFoG(DAp*aDffH{-35)?{O|Zc`4}83r2<;wpE3sJ$ zar3y4V_Tb(@#m)I4xjA3qq)NV7pLd{Ur&<{OR$9yR*PwDZw?uE>4tG|qEOnuTH{_- zchN(aulw2So5G*j7`CFNm&WjiJd_VY2g0He!Fnoc`OL}zia-=ZMj)CbBIF^$ATtsf z^ANER!m5es+7>{D78g7b4IO*vqO3RQJcMHhco;Ln4qXsCG~HKP{C zVG$^84Ni-8660RGqm$Pi<`r+YG@)PKmH6OI8#BqasJSj?$V4(}HO=R$_C&!Re|5UF zYqV%TJyy0K{>jkT&efm6`H3m@ZbJrZM;OKS;az-V^xeF3OPZ&br1{km?H#D2$F8sH z=zhlkpN~_x`Q5~>xPw&R71;4+Ajl4gU2zA6r@jl3W>T?jRL7nQ`UtGxWv_(5pYu>v zum+PH?gMFoK;z(PhHbwm_$m9k9~4A}BX~w@q`(RG-$5f-?BMsVrmMhNh)^KtU7-0RNn4=c<Jpr9{(!t+kchFmfJBpF9X0#cOu$5h{c=fE0wSuwemGc1gL^S*)B4! z6WP*AF*k;)1|HEarPy;CD`*J84;l2(H7cZ9%Kf`ybcDO-?v$KDe>x zsej&k^mHyh^{oR(e;459?)En~h0KljuJ3;H_YVwzccsU?Y8ImF+tYu#&ev{GMIA%H zCgC?4TpWjR70d!<&^Brqn-$i57U8#od6S8`!NTa*G1@e=l!2D8(4rbLq9H>9sR@+g zH6L*7|4;co0n!x6kU)!R!S|&Mv}O(2A~81@ST{Me1xqM025a>+CZtsa$cL5~(Zs3Xc{%1aXYd@oTho?u6ZPBjTC9+3f!9KbNT${vI z_mH^mevEWG<>|dpt^k2sz@I&WJ3oOIjsxHy+C^dF6>b~YO#j^I>MWct$h3*s96}m8 zxIWHU1)&K9f)}(?$3WMrATuMOjm7SQ4OSkFAZ@c5k@lsyt)Oe!jp?L(VS4`HYkl@; zuCRaKZ0^YebGcP<1FVV#;O3sTEg? zrgUCl3K{o!eNpdryqQp@i=~bMqw_M7otL3^Y@qPsj~1)}`8`jP-}5B#{X4J*Zva5e z%=5_MC+X|n#^r}!2)5!Yh%kWh0$i3rSfI5>5&Lr}7dkwSH|(AGd0+x~QHPA*s2I3f z)X#B;2lx8Kg&{tY#wa={GR<^Uem!H$Eql@o12>+?6*SiNxBjxpaq|HacN$R z!dKuBnD=#oz5%RzG@>6iiM%5020$~J?x_W=S06t$>uoURQcx6<>9JC1CVcK&V%u3k5b!F40x$TWJZdo?KJJW-eI$=NmL)gu zAS)*GhKHtU?H#db`>S)=@2ttB&I7hICqI}B8QU_z4KpKzM-TBSV>|D^vYBt}&7San zubii_^Irjw%{^G@PPBN2SU85>F&J0_N;8m~1;A?QMo)L+&5mGC4b#yUK9Keci93%pSu;VP7NX(|E$m+KBu?=Cs^FldXpe<{>Grh`jwR*`T2*XYwezbJ_T(KyaH?p1tzkNFek(T znCZ@izr|b-o8^qYO7^8knf~UV(f-lTu<6Fnar8T%A(ZJt@7REu?xebZ2Uo0b<&&+~ za{1Vcf#q%$u3uGJNGV5Z5-lA<#spM@vd1rL3jH(#5kM9Au?8Vkvm6|URx5M7^e7kT zGIZWij}^V63YNu(ekh24VEdr+#ohb=X068ttE2#ElH}6oVbmoPy(HW~@axS%5T7w< zVf1V0nV=-pl8mH_iiJ1=ABgZ(skhifa5d1+_?byHgmNcf9B+Sg6Z zdJ^*>EEISK9gfGC;n5N@e-XG86#$XY^?rb+nki~Ny)kI?16;DFvoPBs9En zmxM1~mkn1Za0Prz6NL2Os*9kAC_$9q+$EGC;X|ZWNicMrQqWKc&K^Y&gn7L!unZpj zfu#HW+tx?F^!$O(vc`eDtD*p`ys_;3L%2cOo?NeCYF4Au8hqjN>jM4LHdL9|#0_Rw(LD5pPK?4@UqfLb{-> zW=%O>DM+e@GO!$McK}1&@Tk;UKeTzh@zkCJpIOUhV5{Q-04l=A6R+j1x(HCfj6!q@ zLT~gjHhO5O_@dxnW7Eg+f%(TjUuw!9uzB)re_i-%fUB5x zeShBe{jvb%DCI)Xdjgapgs^lW;<^+`O9&0XQ$d%((VDf%0x}vjt03*L)fY5*fij>g z@Gj9fuCt}?4%p&=Ww7osL;feW3>baYga7-x`>C$Qm{z9_fD|*fMiBf)&>2mlPN}V4 zkkoVcs}Oo$;NM?u!7pq2m39g}%k!a7^79qjE0(Kb9-v%N^MRuoA|Vn=Ai|bvY6|P^ zR`^7L?D@y06P^ve51J{^`Xgwq3ga@D$`32JyVXT)4M^3lfpc9nd!^z~?N|}dpvCcU zOm)usjNfO=nGu=%9F6=ZM<_!n)%rrkIgOK z6tOGrICke>!-~a^dG3t98e|6Sd6G}wx0$==eY(b;UC78;6^>h>g%DtBAnQB#W63$r zH>OMW*9xBdtXp)3yxH0E&V`jXU=XZGTbr&Ken&*f9!r<)5z|D*N1g(U>#^E0b* z`~7irZP}J=*_LEkzTeMBAGLGOUFY6&_g;JLwSFr(kn+0|Y2De=tym>_0lG}|F^4KI!AtV%c$oaNoH#GYFy~<2l|0GhW`BMfyZ67 zs$x&fo1HK4#KQbaE+#H@1|{86f#@WFq~dKely zhDG|4uJ`hqrnY;=<2j#h?CXKPdw_cYE}T2X9m56-2&M_!+3?ia=i#R9t4U*MJM6k~n!spsp)fUMRg2GBs{itw`pV0S3)JFhSQX^1<49f;Wr5S;ki0LA z^KvklPseD$v0wnNXkjNo9sod><u4b4j?H7cArN-|~MrXHF@_rG?Bc3A4K=&D!Q5InW;Hq~rO!=)C89 z6f8c6(EPLMyytrWT)u230J1<$zo$!tg=o&QO^OF5IrT54DY&wRP)!8i3#L_ND3a?s zNxs_0!v(@~ftor^gQ;8Y+qU}y6K&F}($d1&GYa2X60)x{v_4Bj>NP|C$b6sqO0md? zMQ*U=m0Mw+&}01sV`_LVr1_H)wCjKMXRmFWv`E0Xj;vSI&-%-mvB>2Gw$w+Istkox zJZ2h^GNiO8?O-Q8tdvbeG#80;Vm7JJKw4wWGYDN^5XzCCX)XSb}Qyx$G7 z{wMnuOleB5uMdx)8{7Byldvyo>3GsK42?j zr6pW|h;ji3O&sA8Uvr8hM98ZU9u8B(pTh8h(oQPl{`<|Z@BH$lJnwj&=(fcY_AyWVxk=x5 zp)27uH1_mue&B`75596s+XI}SpPBF7*}C?7cXH)*V4VH2>JMMKr2K}O3UgH~Di$2x z5y&M8#@-quQ|pjy=F$(e1FI^ z-eiiDyTCmPDsAC(ty$y--SXfB9n>ZmPvG(_V2kynZT{!G7uF5jv1QlyC;EBE<<@@B z!n#kcsww!+irOM$MNN#bEo3?~c&$mChF+XbKWO=@gcr2Xp)Jlfvs9c&0s&c#Rjx2E z7Q!nd7%@4f$$!{tzh`S(_r@Kq*{9cRbZ)%yp04KcGkWUqt&diHU|D_my{Fa`TwYdW z*>HGAAeU|JHY73cf)%JdW-(x%Un3`w1dKSFg)G=v2#V3RLrKN?d zDvN$!Xj@mL&|K%qh@tU~*DnH=2?I&Ld(GC~dw=(I-xvS)*Y|w!uBQ@@uGx}0VZ!`J%0n+EHr(=X z?{BjrPe*OPqAYIDi-tuV&WREMRbXM(EBpZ$e+MvP%j1&=A?Pl+L+}6bbrd8FP0Tcl zHg@*jeSEANf6lBaKjVz@;@`w=^I{Kpw= zrIG0KyL$T@ChGZ)*#Wp@cI787sVlv7(aZ?`fJ^$-PSUUS1u1Gn6aR3+Kog1>9u+4- z{b)*KE`iv)HCAl|WgXq*KWyS}y=QI9jlX=T>m&d0qn4jNwIQ*6{EeQvtbKiO*UgXg z{3hdikA*^h$()MFsY)Ft8X#cC4UCxzKbdy|a`fRdAVGU!0K}um1VdEey7uk~4g-K0CUmIaZqjZq0R&R!>_V#bEXXt&-gJM`U z4ig)M5?5o)G>I-M3nHhvl3AtjdL6Rc`&p-8&yW#4j`N!>U42tZ1ZsCGmEG9c`}j-k z-M^|UD%w+Msv-@uIz`lO1ziRd5wt1Jf0Fkns-X~}+mHw$W7(j?@48c|2@wi9CI{f0 zS*0^Cn_K?5HxxjrB+seQsvX7g^H>C&TAl{F%}pUek6uj7CNds zb=bte=Y_4kzyIQ|I^OoRTRR?jX>0o6R%Is=NQqOx_Z~GZR`H! z((=--u;`E@Qr{u)ssXmrl>3s81{^?%AFQ97mDJ2Ej4W8!*8PWxc%Earhp(JH^TTJ= z6<@coGE8d60LcwK!Nh-PLKph#x5W*%w05-^5Y&k+1r5d;DJ3AADwW z?`_NfcJrHWez^CKTXvtggYrc1)P}(~zI$i;j~3Nw=9I@)+Lj!$wYxIFT4~~Y4&IJo zErw4ra;wmtdbk51bXy*th*+jdZtb30tHQCcvb?$O_mx$ZQ{Xdt8lCZ4y~fj0zk3 z!v9Kex*gJ+J85z>>qU_fa6P^Hjx7!UG0tX82(NT>uk}^vju~Oo5>Yi;D0xj_i=mhe z6y&1;dl8^YgQuWb$>Q3g0((w4%b&amFV8QDe=B5~7lOp*p*hQkH)n-{aV{gvy<&p`J1uzF);y-523V+t zMOwJfgEzZyt^=ofu*8KrFKDS7Vf-g6@dIs<*orF5GJ9|KzbHZb8fRC6?CXO(5fyd~ zMJ{?W*&lA|8tQCx0??93I4`&NJTfyDd(l=>95K|XgAznpB1%)_2R#V#3^@Tl^cc`* z85b6X?KgJyC0-rR=Qt(@;L>?BK6A$Gf|<=74$k%jx3CR%~-QJ+4J*1_5Wt&Vks^OhZe-5Ms&2- zU)h3DWumo<+j#Oh0XYYt(ceFKI$-+2%Fy>?8#{Zy%M^D!FRHEii&a%+->ff;{%6!Q zS0ECv1kN0q_~&{u?#XxpWCWT_c*cUqRM0MWr53Kv3a7d-*9)2pnFM(Qdgy!ZYuwR* z2$3Zvgl5L~+xtg@)8mkRt%IEkUQ|I;0?qoHH|_Y)1XwfSZ0YISZFKb96)!1JVI}1v zQn6Kp!J*uMsGge9;mO7%NDADpgs^R1Y?{VH%>&~%ryTWbd=Z#)=T!XPnT4T}U2k+# zkn$-#fydw6%0GOiPxzbyRP@Lu|J|CFGVBHNuM`Eo0XZl9NJ*fF%rnsVIVtnci3Xp&7GH(J2o*xCD7 z%!)i*60vG6k%cV+twxaEldlvADDV_pBIh67s{y7lznGLB>d@^WzJ8bnTc?g4;MI4?+T^<1ccWKR{gJ9@PrAk5AEgW zGW;*~ggM8lJ*oH_vshs-ufQq^LjTH8=nQ1r(v;WfLw91WZnAJAGq`}5bfzwh{1 zJiasx40I2)b>CH1RuG9Qbxxm%>{fvcc$v>hza`*HkQC?|&}JI*XBEZlEnR)%k`Hjy z4#2EvQE9PZe8TF^gv2$dz^6#2UReLIXoeF0gy^O5z3qF)f=Dp=Z{6iQ^SNKOT>f9T zwLdtaww`2c*fHqb{BX~mm8G(M@$A^e(Xd1g)D6%YBqUh#ZM?25ej|Zc&@@K~`nT_9 zp9A2D=3G~^$qE{>ScWnRO#8iQUvBS7AK$8zcbroDf6lG0`09*^^?yUAF+U>^M!3Nh zRyt7U2PI(>ReNu0c+u88YzVysD@!3r{;LL7xIst3$tD+hEWC6!X0e5cptUC3nkKPf z5815)=pLVzuyCI#WC24nuqT!J($?<&jgxQj#Lx}i#*W^Hs^amMBFi|#6)D^!&|+%p zy+BTQO7CS&Fb07$)MaWCmT^wp4n4oSKe1yx&U;kU6&6-j#jKAPWR+!VMFl=3C!zz8 z&{(S=er^1SR{lAay4#;`{?V16-|?Q!jmd+1jpi8_9(pOUG3CoWr&dK*6&0wNBfUpP zNHFJGWS(|{IxS;*I{^Z?>~jD-(ZqqJ;vovQh{i;SnMOfXH1vt0aHzAfKk?#Z+j-8c ziusq%nfa?C+x(=dq|O(i8o1mOu5@6AAB6fRQgKg!*KK%GDN;if$^(vzr35X)QVk2e z$qzS+t05%B-!c=c#3tL7CA(vQ!B;!TZ0$#P`xw6PN?7=#34?$Q^f>NKcWi0+)+C!d zDQxZOTNe*Uo-4A<#Y)NSPJ{+C$cQiTCn*2o1R+eI53p5J)V`uL%s{|hP%Xwa9 z<&3kc3b)M3sN#@sG8dP{qED>EjUjp8*yo~{p|MN*2IYO4|9PnOZ$9%sEkBu9Bl8Sr z>(7=yJ9CD4E*xAXpj6OPq4!@B_=zB)bGjk~a=_1Gk&=^X{I5we^LS!@U~&D=VwQP>OYpv3>%l^2U+Lz_M$YM9XKNlZgyuy0 zbN6m*{Q9w+^QhP3&^*UW& z_;vI7U;AC#0~2dxo&)*8J#9aG^BJM}vr8k(<$!RL*1_Ou&U0~F6uQfwwvmA05rB+9 z9H>(sk)i)rdP0dnpMnHKy`x3q#g=*D{L+GD8#{Y{KT)>5V}9-bUQitQsiD+mS|qYW z!zv%%;y{%*ITL>l0h&#C#t5D_>uVlq@6A@)mN6$5MnnjUrrsCAlVnq1n4n!qz1l~% zApxc!Apt|k8p1XU?zMtkg@_2EwcF>qKe=_&&cB*WGmj(whK`=QPbn>oM3g$+7qNFJ zhzpeaCvSy-0mOWv!_W*`#tKiHziJ;G96Xlu9W|>e%Wo*~RaMki*y2;Jf)LeIM_i36 z5~A1H*tOP}!v47uziqqS7e4ok_6u%(to@{t@SRHB{BZAGD;G1Px;TDTXatcaRcK+( zbnxF0`~f{Joq*vEKo(er%Wx@0gP?|Zjvow~hG^0Rd&n`vSbS<(@!9J;dd4lAILGyi z=6$d?&NFh=T`r(SV88z4ZPNy@Eg<4t)-?>IXf0EFh$T>vDlyd z8~{&)YYLtzq=%ff4g=O%@Q8vwf^7-U_qVlYv){aZbHnE+*TUn^tDU`%)D;!<#Y|&i zMx?Y|gs3{XD+D3}T7+gLkxtWz!27$yf1&>p<9yX(0x-`;lB-A{LQO@gU;4#DpqPdqSpw)D*^311Qo8~feI zqJXFgaqt@bAXYvWg{l*X;SPY!{;U7t#5BzGpw1J@1h%SR5;l}9C<=!gcJ>XtGF~=) zU~&DA;NoO@l!HZCmljG0ki zVF^@;Ke=JFqoE5zS1KasgvZp?FPH51N<-)K-?(k?ihG{w$(Q&|5$=C3@qA55$@=;# zd0Q-MgoeMD$`p(e1!e|kn?m&T5(*mb094>oC8Mv16oGPGr61%;Y!;0zLfBCAHgxpd zG#>Wcuw?GnqPF!9Vc=XJ&Ub>W{*i2MG{MpnTizu=Qs5~|(@h{IG~jydNT&Whlg_?s zE2F10Y+X}qnIQ+LK~ps(Iy7N68K5Gdvq4bm1q&Winnn?t1d@QD_b9E`WPSZ;b1L(l z-*4IV<%a&mv}_T6By8#K+dMNC+Z4BrI!|Qo9udMyQ{&0WQ1yEdp`kU+RzoCgsraiM zy+`FB9hen9>g@iLe@=aGrv-nogiQ(tfMpXHayNiZ1$UbJsvs25m`wkA zM`zC+Lx;HvW8I9X{g$v{%or6KDVQ1pnGDhIPuxm)8AZQSkxRb)jVHhb}lh+rg!p{2pYg_KiE178>-}$j-Fo} z={d$6@w%wC>dLxU`15mJ^ZFaI%vdzkliLI$L(8g+H$~q84cZ6$O+KOJW1svt?Q~Wz z{P2cV6K`OiW97F`cD`}lmv_!hB>i4B?5_5GFpCw@cYrDr$WBoY^(ZiWC^n9)hF$}4 zTxL0e?>{4AU%dDja(BiM~bw9SXXJ>>F^LC%1HUO}a+I ziOL_|*!gg0+W8(@Z_fZvDq*`dZGwAaMiV&EXKB!;y72OOGympD&oL$k;F7sDZ$GuD z;D>Wu>%v8@Ph9Ua0H9cDD#SU`=bk(qjdcb@FDu-;r++xwy4;=b|KY2bPrPw?#*5YK z`+5T>K=%#b?)QDLYYT{89|CVkfaL^71L2{Ps3X0a2oUjo3bhb1R9#hV^;?hDj`>9u zUlgSl#k8=4Y zFf_A&PQ;$U^sm?KX}$fx^S15U^UIX$JYxde5IWTaO(eseQh_!F2?E`e=42+XAbNz{ zv31w)`?Kzk46W1MqIr1eo;cZ@08iiyCvae^LZNpb>EjQ(1#ntXQSpM(qMK^8vAn?7 zEYVPOz^fbrQUpd6PO*1Dd<`jxUKhryJp8`DQn07p-SX)lx1Imgy1{(H-w8%TTPB^& zdJmpHFZ!NXWM4Ny?SoNnK%s~G`pMNe=s?;L2DFI=5{5<#eVaP_?mL=ut*k8hS5a#A z0${1T&l$-MiRzr;3a2>`AGR%UwC>j%7TjmRvr4npfEPyiT5CX({j%zSQ7 zf1>fgb9R7N5{dPdgsiI&3GFcgRlsr01<+s>2;ynH4D<izu(6I(-tALIkL$EdKE%Xes0fgElGIpo*y$=}odU|Tx#tu?z_o*M1^Pc-hi zBjGrIGzlUHFI&Nrj+c8VTI1UaFCFavI|51B8%FI~v!}ahoSy2W11>5&v2kblv!XJXCKMq4(R|aswpU|jM(ohbQMw0Vh+ww(%=4Q0F(}t>`VNULhs7GcRO>Po=zePHO$ix4O`b8DJjIB3CU zP;7vVvgc^)z_Xo7=w66iZ=(v;Aw&N;ZT}}IdRc70N|`jB<YKp7co>NK&4hheT_Q_FQfQu zbba0UTJOMrnWhxmBK09L>O-blY%3|wYTcH0z4e2xx3)jy-@T!2Y>~XR9UZOFsQHbB z#Rb0}gn~6j5W$$`aqLk|AMAoK>GlLlFihu>HM3 z#CpnrG7l<7SgcM*G{O9Ph6k@%YEEg`dMhxd`|6MmK#3i?B&3C?XAu#7*cJZqXs0pcv$ zI5^<2qb}E7-OzG(O(guM(vbDuHiGi1s1L=*GLdM&5+rU1+W#Tw5J+oH9HBGmJa^c0 zSUKFxE+6+8x!L^x_r*V(~y1FtO z{9J)cXcDC|j|K5HVnOKKFcLYm+TT#*H2}6*7!!2Ti39`WXDD+~mK`*1Tqoyu}#S zP_98~`V5iGg*7!*Bb@4(wK^W^=>N!o>u%5ODX+1QZBJP|O}H*brmGK8!B$461PRkx z>%N_hdyZPiJ?)gJGaH7XQ|&nWeMF@|eOoHLGl4CIq4KV_h301YQwYyIS~V z%LwIMCV}WlwQ!NEaZf3YerZloQOPkr?Ll;Pbq%cV>HlY62PJyz1X_%vANRBmQX0W; z@xc_53bsp-r!e69uQfn=9L+zeS>4jo*_=%M46S_wSgoLIqRKj_ASS_Qu~I{6G<5!0 z9y6)~P!zH*385l}77V>lQERFruEr`?gwHcDix0i`5Af{Po_l}#r}iTXedaka`PjEx zZ~F6wmLKJufSgEBMFQ z)>F&NFC3c%V`F`D=e=+ACw~Wln9wt(X7DJZ0J)acIuj%=_77Du2+;31dGpXmHnE{@I=Hm^|z99Bss*dprM_7fNXCg}sQA?{Mq3h3@QTW>{>SzCG{`i&er*`(IzT2H~$O#1XA5E7a z4Q8o=L>5s&DPzab#T!7z^|pgDYF9L2xbNdVJ|H4T(7n#)-+|B~i|}9QpfvC#x+CI1y`j0xg)qUTM=kTx>rbuw@u424eJ_RRzK}k2 zOI9J6#Mj!I`%M3l=1~?B8PRA#i?1W5=%QA5`5vWz^RNx;Y}jPMb_+TUi0J(j1*4WZ zvo0QfZ)I)u|2pCqU=((Bcdtvi-um3{{p!eX3-L5oK?t4QS4Yq}%=<}s`i*0?Gta?1 zw0+Ox1D<<_5bUqKP+*{DnA1W5bS#v4P>rS_Y@cB#__r8`+Z_V(&0pWAwn5S{l=mU77 zsTgwZ>s)x72Wf&(b=gM097p?` zbN))d9Qi$=eV{Z#Hj@Gslq}=~fLyIpiGkFp;zW6ljh+2{|KV#kYpqFGimfvWFiX`* z5eX>qp+XCVhFX5OV-K+fpv_!z(20Qf8Wk7JS{pMo`s!aPXlQm{zyCS^bCYXfo~gti zSNHYacu&&}oxRR>rGlhDqbO(^WXwG|@&ODjloB}i0P`KV!WTS1iG<5S)<>_Xopt4i z5B4Rc(Wyh7Uw}2XX1(xzd@{bsh$Zy~L$P};9@_7{Z+qjqA8*+9h24YMTYOJ9p=Co_ zv$Ie9_CE1@9duG@oyhunM^h?u=eq8`kNk0K!~46sx(1H=#TbFCt2ZBOS%DF^gV;a8 zR>#hv_P+y;+xSvXPv5cHm}g|3Z|dIT`rhM8grv86Lj{f3{*Jh zUNN`k(nB3Tdi2gTjEEZu0G$YE7mQgNd%>Ys|60SQ?fOr@_)}}g-EM012 z?al1Je@El}!2J~!#Op#;m&Z+WKKOdj@pran+-Dj)JKH$+0)$aXIPOcXuMs8m9%0`I z@inR@7+!VKLyORA?yLXr&$?sQYtM6Z{Cwl~Pkwy)g7XzD-|$8!bC%6!;hBv%FKUQP z-_NxV)Ob*ANLfuZaslwjXvdDe1pxb!0H=EJf5<#*nSoJw=)M1SyE>n__N%Xcdh(3R zGnM(?A3I*T{rQ$Jdf7myT?DK-CgHao(DHJc5eKRbz29DXE{SMW7FKFO10tMuT1EV~ z=a-cg41c_K*eRO6G}<3Y0aO9I6{IztBHHwY0Z$_hO23*IA)`L(L!DMvBYySui|4+7 z`2RXONUUvYz4P&1P2YHYSMxX5>}kEdv9q&MJ9kbKth zyj}y?7Cyp-kPo4<7+%(cp)QH9tDyeh0}`H}Z~r^-cnQ~iT#3-r;n7>%fxRM(RjHs_|cpPU~}_8SJL-i5uhXE;W74cQ2RjKhD3I6 z4}c~l(Es;*60VmoJ)Q)%_9t#sS~n^So?fTfT_UK{hu)v*`OyZz@B>jGOUs<|XP4EC zcHE&h`NI=n*My)`L&<;9(O3UkLvyFM;mfz?YyR^b%)7qS{I{ETI8WqC1C63UOTwr# zrsZm(erWYS5*jG?;e1!90knu|ih9%ai|hY&_;G2+U2h4mZ5%;vt;K*Yt+tp#adU6_ z&rdh@^$ceHtti~pqVHd4YkG&xrV$ONcue!an`enlqI^XD{uiGTF(hok@-t_xi=kO#D1v23LQad_oHNc1t zKrMtV)FDF$QwiNJgqF*wT{}d;&-&g^AM5<<$+axciNvRV()i9j?d~Sa3>?OwUw|3p z0ZgN@qT0}ukJ8jDhY$$wtnzXz0bNyS8dqMkaL#qPW4aUGpAAj_>*!~i4p8sgt)S2F z8_^~{?s)rxIls8Pe)fM|IOou%ew%jr_k8$jyY3@bN7~ZvUp&$N@wRR!p;X{F+NWFCEA+G~4J;YM)T0R|^d%0Q?E@l8Lt%9&{I_qNKl>Vh zKQ}dXyT0FHB3oWC_dO;f!4`lw!t?BWZO0E&8Gn!T7H!;rlKKme}K`q3YqXS{iESM$BD)~|?y-HmB_ z2YkXSBj|RSwq=2upha-0_$Wgnqa8Qm{cMOi1BgzPapQ^KAVl6BLX6Qn{+R~cba(Ra zCfBk&Cn8_HxpnpLpXvC!L^8OU%#aX$YYbH>(`GARtm$mI%7AmTutY-&W(c~XDjL2a zx3Acha-J}J9o+&uw^%{*l@vpAw?bjY_macUxfyRDs}D^r&aweM$j)HdVPq2&u5T&rglc`IFoY%F3ZC9kd!CTyG>2af}-Mo>F;;{ z`H$NhU;3-1^9K=~c*+pUj6fPVDH;Qro%H+-Bc1n|uC9S+y1M=a;F7sjwWW6GlDJ_m zN6FT-=NT^A9rXRS{_%`kW0^x6J20oEOPOh zU9hL$huR0`x`Jcq+Ux4;i~g`<$3eOiBhH*5WzJGav2iRtJ|_X40sDN7K7t0b_kTig9t?<-gBvF0vdXwuc1=jfvp+{_BiG+u}S&#_EPW&(|%Pw>DxL zZyFd#@cNbl&N>6aSD7UK%|qrLZwtpC4ODqhU{jJ%nF8P-2jHMBfQxF2iesj#U#y`* zoXN2B=otiaeh6iZoc*s9tlif6{G)3Jx+dSaJSRFg-IBPjsoh-*AO?h2MzAkpTIB7a#}Lop{Fa zg9&nzKs%t2m{M{=BoiMBSL=2mShgQBaa;o-*}MOr9Y_QF8UXoP)0=jlnLtzX9D=mt zJ_}%kVCUxGy-|gV@Fn4(xx_U5Nc+GXU+T2$kC+I!p9AoY1+^cVZCZc%CZB>L4RJ5f z3r_{!{FFiuf_1*2Vk1lcDg}Gm-7WugQ|qrM-?}{0h40?g`ugq9wSLJof~o*>c9ig2 zEL8FINeUb*xqN`dj<90r(mfG#Zb9tRbm8eU&b#WIimN8_ zIe=aW9DtEj4|9mts1gIS)W%J?=%h!=5IQADXmowDNw@z`6KrdqQRqzTXC2SqrbK9K z9w3v_Cfr2p-809MT`oi#IJe`s;WT2h-0y#25Qdf`(QYkmkB zrSXr}@aSvpw=ymLx;&G~$G_A1-%o7pxy>|!tpIz0iFKv~30^1J-IdD+ST$4`kh}c( zg|V}e!IpsFPejcCHrc6=cuVS!ild@m4Z>^j2QkGfv!HMd*co_pKY6GT=>c_6Cc^t z;;uCfP*EXrQ3UHurma-)p~%SvpW#8#P|tv{p_pG7mEFlSU75*QG`zHD#a`KC?eqFX+L`C@WIVkI0#Tq1>ou+y ze4fp^2vR&fbpeV!K=14AGaLnQab3+-B}!dY>?$Hddeu21Kq;e&>>U@h3sS7W8rdq- zfQFvF*ME3-=hjI!EzdM%^`?%*4<6{ap{?8L770oN?G<6Lrstq>I5be_2KfNFZi0oD zNnJd`8v{v_t~WG}$b?SLZCx^Anc;Yn^88&Il7~A^EHFw#=s}N6S0AFFLjngt1Ffmd zy%TL~oaQC?0z?%R6%{WoihZ`qk$4;k z8G3J)t0w3b9#@+5RH}T+fH_~I;;|9K|4tS*?#SLX`G)10&fIuM%jO5xb$-rwgDs}W z=@#M3eDsN)=YEuE;0y=eDGz1HP4~B_l?~TXMAs$C~(u7=8oXbm5`uH1hJTw z+j{eSc{``n&N=Y!=DB5sR~9>JQPi`Di$i3Dix2tWjYR`<5;3YQ%wolXJB&&}Q-}M; z{ZGnG$H%ff)0vNcyX7Yp#j^B@0Vov*jKAN$LB+9W6Hi`tYl zekXVQ+SmP`^d!;~8d}%lTN?2I90$}0ZAY{Nq1qBehBN@unsy^7hco~UyC>4dJY&cA z^&Vx&nU16B>o%bllnF+Kg{l(#RyXMXF%8fJ>YQboWl_tl1@;rvGUvs^e;ILAnJ1c3 zG_etME+RuQzNz3CiK{VZDpcXfZ;;lot8-w-eJ`~fHe{D4&(ZL^FE#(;yc^4xE~qsx zQ6|LR1*u;v+-`r`3>;%6mn(FE1D!TB6Ex0QSQuq<-(V92d#+>QFWy}B!RszDema=( zsjsq0rDj+^eW3kASD(vmZ(bH%3b1HS>fC{BMfX#$bo>h7w$*Jv1%5ga*OtRFRE3}o z5G)J)14|t=5D~)j;`p8)BmgEg{Sl#$;PvTuy}bVa6v5TH9U$vz_H_E3qZFq_gStO|hOk}G_;%!SgSq`(5xpf(m>v^6pK>{!op_4(Wg zaKo1eUw?j+!&T>4?}Ko~z#x6AHzZ%X{Ii|U$3luzYSg4Edqxanfrylh_J8p-k-0IH z5rj#-gcBqHiry>v*PV9q?SH2ZJ-HuJL%kZb4qAX4)k7cPY4kZ3f=U1l2j$}^v=|}Z zWU9;l?!^Ns9KHTOm34d8zMB2<4s;64IYWypN6_6V(pJzsC<7Q;`>AYt^<>zb zXAB7K0KNl>VH;E;U@tPU$`x{`*0LucF&|707UfbVgie^rUk_#4miS0yIWjuZ?rI;MR2F2DLT0EEKxkpgr}BHJ_R-h#m!BI?&qm0`Fju{ zLE<5lV!s4H5%98_=eKoEs3=IDJj1#Cv%5afa7)38iehWASyh02W)^pS1}vsf+05ji zfslqpE;QOY=zu3uIX@J-;TbsWw%nGku7U5|QTpDh5^L2!(qFfAch7Es+n#9s>`Ob# ze_I$aX0F@Z_6U$Z8v8D)Eh;utd`?)*`7vA7gq74-N=nd#L`g)H#I=^$CVDO+g&yDx zZGc|q2}>OImOSpg<`jg_s0vyjBDh%}zf03wB6MqoA)2(G*Z-eNJhEf=i+{arL8~b0 z2Rj^gv>KdJI}}ll2&%-x+jYFH9A7LAg$}b0{JSX!>~>6LH$b#TLV|=w9$C{aolmVz z=Cl9vOe+8O+qSp=_a|m;#|*Xtytg`J{_LNWRRJ2P^x=G0=r)92eBSxKl8;@Y+z)>6 z%Po6lfv-BJ;{0pQGyfal|NVC0;+B>~C%~0wS)V_1p>fUb4te1#H*+zNT6Ie0+)G!< z&u7h$rB7B>e(`rtw0-?>cKprKd7n0wS^~sDM|}usq!dM1dnh>xnnaM9orWk^5R-)?n z^kmu96yeml;J9Fh1Su4lX0pI0P@(mL1OKjE==DTnXrUWna4OaNABYbUHIUHA|4un> z|8Jh|>lyjKdGbsQzqr4B$BlQS-|M?z6bhl`f-%oH>3Rj^@PK(kO@s7MlNCQr zDT}2^o5g99(;YZnd0d9aN78Ur8WuajP^!MIjERlrF?%=uNho@0+ZB~o&AFf z04a1atBn!&{~Npe^0l^kjtigu*`_}{x25NIc%W(`Sc`}9zo*?GGB!McB@UdUgs0a9 zFG5u;`rcKgrG*!qUb=WkYnG=rcsoD-oxx`-OH9Bx@1is0Ljd2uBN_hFnk;WSCwei& zs~g+d_{4_P=70L{!94&qW$N6+J^vrJH2iYgK;j2kPw$Lrp~5j(kg}MYvY45*D02*= zo`s=>3UOF&III-S84lDq!36Jl8sF962EU7|gULTGs5u6)m6ceP`>#ea8Ha=c4MXFo ztNmTCw6=DP=WCm1Jdp0(Ps!vyJsGWoazIAuFgx8acMT5ywkBd+3r1B+3mH$)Q#c<$ zBB0{xAO}DMp5N@;e0;3RlLzj3q3<)b=xVjEx^7;zhHg&8-I*gj=d`Ty*lcYGYx)%Snr&dhf8YDtzXTkhS) zU`(;WG-FIL5CSnJ0n!Oc9zqHUZ^Dznlm0*wAP*#j8i=V0CBZbCX24zUmTk$h)w{OL z?#$ft{xMovvL#o^E6MZye8AG(+0hwkXYRS@p7T4xmXVc>77PLCOi+l?W?CDM`IqR> ze+b#a_C#mjoDzWONCZq49g2VqrlE81`hc{n0cB|y9V_w9?wSvpHC`1~>{v)-fG=4n znIL-D0$>K7{6Ic?;w^G;u=&G_O?zMYtl{2Zn4t~R;678eZ?%DaOZ6KJz-uwiFeDnQ z07Zk#uc>#W7|K^R?A9?nTjUgEi_!mhFZ5eL-}8$nYtCA|-CB3bI58p=mH5^3Et7!O z=3V>f*vEXP4JJe55vfSXH%c)8<`^>te-t(rp1C0kjHRQaxe*BCau?2=f+g-r8uXMHILt#{A&?}4 zn*eSlP&NYrJDG?TLi*MS_C-{C2a+f!-L2)k{YuyfW%FxwO?YbSp86N!=ehTV)`e$} z30$#aTl+tu>ooxI?7P+X?%b92*Nj}A@$XL>UO!sfRs+WBExW&b>6oIexgOWosx_;m zO_fMC1u_f;^{io&G%!{$QUSFbrr2|C&nlThwjY1d(HJ#4b~>bPY8TjKvoRM zyQ$A0$siBG|Me(R|IZEY5(Omeap;WX|B7JzjV4Y5K?g$+p(ra=yM3|i@<+etd%o+r z?z%GNrF(Dj{qdo%rG4CW{IiPsnq!&#yYkQN6~Eio8ot$FUeiX5YR$rKuYs^)pq@3X zmKyf5tuG?$OoU6D5qy6y!fP53t%`spLns0yy8k_eB4D){(02r331DkSs#Q$Nig$L` ztT-N<9r_1d$|@#AdVJ9Wlwn?A2z3UO(vAQGbiG?5VCOg6Lv6P;DO?!@FkmAe3ia9p zVEs1NV<*@e2Zvs{`?0+j1jEwQM)=^ml!5l4yAQxoK$}fa^4$nNX+XHc&}Q4?Pyl_E z7iw}F&eDOIOfUgh7Gv-BOcbW20CvYx+_pIPvHUEW@S{gVPh_Ww{JWOqywTUTF0a`4 z-v4dbahh(*r51ozV(fA=c6$x%RV7wK#ivXNDt3Xi*&-3y)QaHSRcLv&9N{$$h&AqS z3`l}twHavp#MT~*5KsYz3ZTU>-|cJr9r^~-LMwRx6t5q!s8mvn6KztzA_U-Jq(=Rb zZhKdq4!|2_HJGs3S^xkb07*naRP}q=dbL@x+g00(Mu36aQ zF|keq-j*8500b4Xw{KJe2N~hgRG$iP@_lR*GabTVGRZk&~1Pouq4X>@<0v0 z^$iUtL?7J2;Yj(f$F{z@x7J*x4)?)(IfI94hKdTvkbpLp;9dfdn_)GJ&QdD!Se?fe z8NjI);8*rPdZuM~P6vS1+pT3at>M^hi+!FMW0cXae;V!Aq~3q;-uss~Tgpyph(!Mo zvt+#rJ0ei8GPZaP{M$oV<^n2IpoM@Ig%EQStfc)80qYFaLoiiBwE}Dd!2^Q9s0zi5 zcly(Qhhs+)NgP7(ms}n@iDQV<%>f`l52{?{B}Q<-WdQ=DV83V91!*F*eEEP2S~xgh z%*`8SS2b9hT$8;}#wtUyPXM_Ab3I_}Qs63yz^rz|Ty2k&0Ju#>Y?ll1%;Iq-Fe{>= ztwU)(X5|m`z2ys`$fupRBpIzir>U7m??;SA1)2YxA_~ zNc2yJ#qBEWG^18xY#`t%6BJ23jm2YXF7-$aO${E&+}0 zR&|2Rad0>s*1uN9?)>ukp4VKn3`DkJ$n^Q*v^CeD6~==OyAA)>bxFtwrNEXJuvmJSW9_ zn@3U3OxBb+UPY)DfLZ_+2xSBqWd8}>upglDz>dzx4b^0Fz=c3r(|De%?%;;ArGxS0R}^z4tOsBjBOIGk_hwiAEE9o(>(WneO1GD0NVlF4?vwVEOSb-rk$dZ$ag6sOCux$ zf66`9YCEgQ6^uOtupj zyO>JS9wW13+zpt!2=4JwB>gl3ax=_b)R{%iddE{l1xSV69|3@OehB`>?a134MqZK& zCIBIXZ&F(7gD3PN9ZovzmQF~Df8W!Jf2hd;6BEZ=t=$qIyEy=gC8Spl?BWNGS?HRR zVM(B|73B#t$id+#xbfbaJ9p<-eB3xD^AJTy0|PP{B3FfLHX!^Rihmv5@U-cGGNxmn zR3n&Mfwm`;!BIkVjR)p>04}oSyVER0x41!?oiIo$(00EUMuiW0sSoQWTFrav5dGLl!xuNIkT>~t`_5j!b)Cm%SMQu=u85{*DKyb~GaL>@; zJ1+ut0)s5JrGLGElI??9)NxU4xA1n)(4pkJ5ih!8L4b!4{f|WK9R_6*hFQRA9j}`J za=or^pEIIhZbB~HVaTI^a*3!jz&(T${ky^$E?4gk0Nkv&30`FYKa^l}-;`)>w_@#K z%gMNP7&JWodVNi4Q|&{QQ!+l&F@SRc6~NjnAyOpB4Il)l;~1`yI-+YlkP(7wVie@- z*h7r~hy@`6Frm*q#4;J_&U&>~$XpqGP7tm|4*+tZ{JQgKa;3p!ony1V}*Y`-2ojKqSKL!P;gg z0^l&HxbMlD<-3*O-%DNGkZ4+Fx>f@^%y83cy$enAL8On>$m9MVe2A)x&mNZ^^5JnUSl} zdj!B^l8Xo4+}{aHK(=)^FUYNGTk?VZ0UaC$KHq+(^!LkM`0`c_PzUN=*O3uKZu@Ji zLIANK0$ZV4Tg}#;Go`FnxF_E98v2w zZ+2vW9R?>4tl9C>Y9a4!6p7sm=*;#%AmblyAhOa6t40BN0lCLQ_$@E2MmO}2V~DK~ zolg;t07jV`MwuJ%cbr$XrGO)!B>|p8Um>ID1wB3sZYAr6zR>$tMRT_6F7GA^PRvfK(JGc-j^9GjE+Q2$)L!^wtM zC{yBJ2mFBM>i#+rAgzHKk~?;K>IKj}0$_JY8qjbQFvHxLwaGjvqzW7y4$1OZ^wu(! z^%MQrA<3X*g8v!|T1gb%3jp_g3Fr)t0NMl-NtZW)N~B!{U@=6FfcK0DJZI=2uYFId z;~2h6JaA34s{^!&3>fy+upl6bj@Y|lm4GUV3sc=7L6FSwxzy_}8&h~oKmIBlP8Nu= z0XqS(*F#L8=TZ9d&4+2)dSgaljnHcKR>siApiKT*uepr@h`lG+Lp2~ zWEugP079UHn&x#E0um&70Eg3AA&4NuYV0~lgrT)l<8YGllg-=yuu{m!V@JMN?h|AS zpydQ13JFRs1EKxt&y;Pi2k0>JU>sARq)I500dg}qhU06eN`SC{SwRzH(ml3HAW=?! zlIzjqIIDvLG!lgX;8F-apX|8;z!7CJwF<~q zVc&D{=!6Q$kgz9tz?K3oBghEBcVz@tqZ`I%6~`+pW&ubGnm9{0keVbQnc;V-7hO5F z=tswQW`~m*BFd2+f$pNTo?f>VXNOv9d0Wh?KX9y@13;|C2s~gN044%Q0gmqX&H^IU z3}!kJ0EeN$(#`e3*M(eME?D-94-jLJhahs*&OLgv7?GDfh;8yf|IhmxI@2B^iwh4g&-Dx-GzJ7Pce6KyIpl*Bi)Av{?=geaStgWxrqQ z;%EA@G>|I^DYrHw{Hl)dTV9Zx;hGDmrvfrUX#I{v@XZwXE>?gjK3h_6SQeY-zljPklAM93<3(0H8220hy}MyF8NI#{RD@T z1dYU)_}9tF8dNv+=m1!)LuXgn0#FC8FsyFba{vx-03@3+=7F082mnw3S<8?iyAr_d zB_s#rutb~X;Lz8U5`Vu;<%4e8zDA@1R+}H9h;8u`ZGR9jo&?y9UJ?R1N}!aEZ3S1) z#~dpr0fkK#PKyCv&E5)7h;F)gRQ@@A`;#1oGMb|&b4NMNW0Ro69BiHM@4{)?V91hRyg7kc!s!RresBU8ZGzDfa8{X!wzW@9t z3X6aWqW7NNR(Y5z08h{w*bPeUL_nifLbh>d=%z56CMVV^2Z#RQ7n`>|y;9&$!DA^6 zjM=SvMf^b)AVi+EVAKWx0MS)$`(A2gL_YLFNtH16dZ52#x9epSfC}hqJ+>6EhR&yh zRc)&Qa@5`)FgFuor3`X2Vr5>K>j7weyOLlA+y-N&0EQ)Lkj!u?blP>}i=BJ`hr^Pr z`R1uYXp$M(Spm3`dJg}?0<1E0CcO>?YKTjF8t>)+7*=B}Lez3%OgcsgfCvmQY7s?eS_g%DB!&S@SYKY$PwTU)inKIgy8Qzh`qyL zrGLZ>gi6S$h~Pp~BG~ctPI75CIi-OPhr=ak3c>!YX5{z0ye9(8sGaaSRA?h0YVbiN zfWQF`z#Cp%$boS_2%qN^kDp6v$L5!7*j zRuqP@&9=lf%>;QnPVOZjlk9){X&cdkorqY_YT=4(KjKbNhD*Ei?4q3F{`sj6LxE(M zIv?1-|KF1U5D~zwCJ-GuDu5vYNJaFRl6znZ1cwCI4s_?IQxZ64KcF&Gw6vLU#DE-z zE`KO3Tlt~J_lAyeZjDR!T6JM?lM{S zdgO!};V@{JJABxg$u4asVDJCWn24Uk{{YM?*f}smWBx}A*owuhP*1NNlmppfDVzG= zq~n7XTX;mad%z5+3NUR!=A=a1<>1ht{BV8Qe=pPcspBpUbai?1skTGl8mB@%6>y&t zg>2Blwe~SedJO7W0%~#_co)EJwp6g|3_u+gh1KYW8R8SZT2cTQVc;y?!0=QTBr}8} z=3hI$_-7~75QjlQvfFi$0>H8uRAe)VW z?)eaaHo&SkV8!eQ)wp4qrzF-W2Z#RWeJl38GL;X`(}^(<;qEECDquCaU^R8G$rC|_ z)#L(4I<^XSn=p2nNWQ)eO1>N67i=lu$cJ7i`EI1#+Kk|vDWGhIu@;E!@*uFN4I1)NJBST?ec+kQ;uLhsXmI_YS)c-nvME+?f-WrF2OuAdW%7PvKzjPr%Xa^?% z5&_ceaB_zT0zg=xnc#}`_IfuA;-&%b002NTV3b<+Ll3~nqP7JIw#dPu-&wl3qUH(W z%j?DdIhP2~rUR~X$JgPEQGGkb#AL%JTZviWga^DG94FHINQkU53V(#&Z4{`vS zW4y2b&FTX*g1H`$%{nXz%o>$3KhY*RIGhNc+*r2!0~Iev3HD^K+3k2eGX*G9fGoSG zC;1e3W;0w9b^C!AWVp{0a81`#rZ204oZVOn1TK z>N&no1jvwSSH}#2?lJ@*N~65ZmOj!}}Rg zsN)!Hbev<2r`yjUH(;!_CwM-vF$!V8BuOz5GHP@z^t(Fs0X(X5`Lz>@A4s%q4hcs| zce}2LcmJC)is5thQvVOY*v*i&(k^2i0@Nu$%)-8LrsIJoyoa8wDVq^`Hx<6i_Sg8E8_90;6Q^q*fG*1<8sM_13IMZ7 zV)(8GOfAWPZb=Z4C<=HUx^PrMNuup@NDR4t&vh06p#jszDo78gJ+A(V0ISKc9o`{Q z0YD7w19ULyy&cozPDd-#rU5So1bhFFn}Fy>+uFjk)UgRR$-&`-vaG%BOKVkp7Rn-o z-|}{bFG(`U59lBGpnu@AmCXW#=xY+eKNBKv1Q2@M0}eA-5J&~MO-1+>fQENGAtgYm zgtn(rVQ!@X?*y<)uy$Hl;Aucfkq?H>5G1m5J?@7RZJWc1=iK7FMQ);*mc>X(RgjWy zLi8f79OjzOA$$E{?4cOieSZ9i-zM5LhZ9RllK&U+c-EO`xlod?LiW<@R+@lpGay?|yrxBe z(JX*A=2cB*__N-Q>Cpj*5Y>hUNfsol1ZxXmR)*p85Y8Ku{hdVH?#ys&wcBXt!TFw(tvy zw$0(hFt;%ODk7R}S&Wo?4@MN=kgI==GORjjYfTT0`5z$x7(~^tZm(|W?U){?`Sy0X zFGf5Vb^!p`dz;Y>450xNOT?v#w#UJtKOvAB(q*^D*@rbXZ?r}C4^fv+d{&D9$Lx(w zHMz~M^N$~wO!h<1=svTHjw<@DB0`is2xfoSivn3^BIn%*E-J}{#kS&cuG{_Fi$^;m zK_>%60r!vMcfj}&0wwu9@BPOy_Lwl&5Byx0BSm4LPB4gNkJFrfK8O1D&{y+EX%Ya<_#yBrE28|_$U;DInQ$huN5BM*s%V>PYS-OxEf# z|6D&v5CG&9dVT-rhy)F7E-Ws%#iJ_ICEI)dGp8_w+OzgQ5g@}1t11Gy$Igct3Rnc} z11e&SURVD>FZqrYfE<~f;Xhr{fuD1gt8yC4!sWV5xy)0?|)xy#NfB`e-5`%HW8CF~ufoydKo-F`#Ialk0VzwzjV6 ziA0;|&_B${&wR?QC|PC{m~pBXb7%Fw`X>Uc78Cjk3$h)9=kt9C2tW$~pQ%{iWb)tF zH#GOy3K-}m0ssKDirg5(AaVFRj5Iby!4byDT-U6`8sy+`{Cx0-B7Xd?+_J7?KU$Le z=6$#N{+*ppljCC-&B~bn{5|>Mg{P_ivqf*;{l1`kDx(BSCb(xxD7oAzf|k>iD?u&-rI@ud=^!IAp-w1V9^HpYPrf0BTe~2UV1B z*}3g-$M#4}k8NunB#D54tqEZ5CK!863{OiQ?^FXg3}*iG%i_=_e<)%A zxOqX&@8(VMo&Tf1g#Y*AQ{AVZH8t}Z0J!Wd*9+ykNXdAOyaygQJA#RzG~_MW76~^9H!hf>9fQHd5`B0%p~g`el)L$=_qf zYfFab?TBL9SOsZW3M`A^)0AtjolyL6qRn&YJLV1>mRS_=d@nBhJ7=B`IqAJ;{>Q`r z`f3RrcZ2->Kc3WlDS{3UDix0qpAR8IR_82l#HP1Oyl)Dmb zlY_&t;`d44bIT*K=3qP-H;{Sp>FRgh+Yny2Vx3<4*c-@elQ>^1Xp?*%C3?KQ?9 z?|3Nuxdk(gwDqm6yG^&D06=sp!KmDSUf0MN^bdS6%Lp<;P)1u|1CT*RY|v!=937NO z&>v$=Xllb3E_Feu1j&pPP5a8#V@CWu(e^p?4cW<_-)TY=S{9>dln2)=P+%TL($?5x zBKj17q@gkU6M!HA^eIFn78*bIlHO)vBG*rvc#H8QNEV z^EKZ;*6i{DKx;)y(}r@(i|QM*q2=t?0WqsJc+Lz%n_xnC*{%ra$OIzKV7l9n9JT-& z2}GVF6cJ;=0uNZiE)Vo*Ke}{u;r9}4qr>rW!KnN%XLz*h4Q5CKSTwJr|HUDa*w_MM zYjjZFpvZJPVj=`Yh}X57#`?n@dq@W$Bxzf05GDSyYDWRg@(6rhQBX9(JvY%dIXD~( z?`?>@fAOjA)BSFNm78Om02tqUxOxl#%o;DQ^1B6o@nr3+ot4d-_SVY}a?&w=O0jq5 zy-!6h0KglzT90nnS65|DtHf?A9oAk6%439H4M53v!!=Te)gn6gK1l$qE0C=rP|DDH zAOZjgpd>>352Kh@6v4tpUa+*ADGu|xe|FKx;h#^mi4MocOh79R_Iz?5z1#TmsRdOlH+@&mF339!LkR?0cn8sse?mU_dsrth`j9wrJm5sKVdLznd8Wtz&WEC3m1723r0ai-r)iFLl=xHSdeHN z9gdzc24M%ePA*c67oi=V% zc-3I?0azs%`y`?p7*q4I=3G77X%Xx&aJl%@%xgb)uKK9ogK1wlJ?)hS#;9CxcI(L9DAnxRVA24QA)sXYAaYD_JVA;883p7XYw#xg9SIu2SPMi~M{v$) z##!g5!O$5BiPYf%?}PITb0-}BBn|_G3ybrwPj_iIN@jRGgt@0{$jeX;Ir$3##P+t^ zd;gxH^I0bVtpqd>*99$EdL-{T9IylO1F?4`MzAsNv}wLCCfXhc zhu%1MQq~WZNCtlTMC|tB5p7d1o0ap&_-m`To3GS1?@!|W_SMSz-Bohm&3_18SJy<= z<9FqDHt_xXiuP}Xq7ssnl=#>u8|!LoTEbQ+D)ApFf4@m(9RRGo5>{RKU}FeFd-4bD ztpF8>zDbB}HLz&D!2FB+(A#xrpb?`|0!z;ro{^VmGaZfytuWxd+kzeXKmTG6W=`(C z-ESufpsyr*?|+DW+`|H>2X@v)LOYJ+_`@#lo20U0?;z`r6c6cyU$-zTf0!c;>@aX4 z@`l4?);7kpB##^9YRQSeRMj9iAACGqMjNckdR`NXP^SaX&=9T$04C|}dU!A*T7qE& z*Ea_5`vC<}8WnbL>cf5Msi(wDfF|2qV04z zG}liUxl9qF#LyYzCi*dGLzwFo4 zxt7I9%TjRue2JoAO0PBlK!@sIh!J_$f^6g=740GbF#`4oppDHBkMwjp1D?je-SEJ^*_s@*Rn+8hUm1KC&}TDGM^{S++d`Q`dm>&lwmi@z3W zQ#aKImB^00q2&Nj)ezpY^aJ_#S>s$+{P^+aIpMI;z0bGh=C{{0{<-T=YuL5CbQeFp zr_PQL6r}k>Ue!IfsLjfz8UcCjz3IO~gL3Y_*&r^tmV4 z?SDT}c;miM>`z;p+xjK~000%h-|Gh5><>G!DaaUGS9$IEQ=A4M4vFRF1-XCv@#4v= ze*LBK`z}5$^IP%p>@-Z9H8SmndDC3?bv^#}>->Apou=H`b?ojXfh}R3&F^28@@cno zFUcE zrNGFFC{iJC?WJ}kKyTNf5lt!%c>j5Rah_96G(fm$Wd67Ee0Hb5c*)f$f zTcg{n{~`9dX8=_SP{I7ymv&WdJks|akpr-yE%uKx!4-%39S=-g1hW+QJSTnk@CQ3M z^ba#f=bScwOzziGN~!AzbRqm|+jX|D6*L#9;SQ;NNF#tz4YUC;aI=CbFP1OIQZ z<@WR&0YdCeM)<8TJPL5dMfC zx6RGU3MASThm(_n6wmyK&iHtT-gw7f_x-1&KtWzw+Asik?bC*P%j%43ilsJoeb3+D zHh$2qM}ZDUVa6C`>YDA=w%0$2y#K~0)_WJ9rhO@X>|b85y*dZ8HKM>Z#^6J)m~04ggWwFt7H&Wn)HsKhdV1 ztjx;EnOKtQf6}E;Qhf4Xa1M^B-X8#DRRpn5wNBlOp+*G2R>DU?Gg@}ogS&9VCH^}k zJ=`)Fw*g>>N3uX!cc!I1nrK@bPEIP@^pzRujMGPZGJd?cXiC{$3sueg+jKI+#ek>l zd;A{cbp3wycB^de6yMm1BLnB0J&oqQvC??1%gc6vPKxg9dV;VE-wtL)r1|@6RsJYC zSRMPmglt7P{a=L0M_~kfg!9fIT(BtJ)=D7q<$ARHt{PkP%S4-cvT<5Y&WLH*N&ogJ z%J8_@&w_J+{Om*5`vV=T|5k~}yB4fUb4Vrrb!EH8Xp+_|ZThJEGbRjI3Z7V5^(6p$mqT3SYU!rI zNBi$j69Ddgs%G@RJ_*0~(p@><*jmAxAAP;<^W6^zh^W2mIs6_D_ax%n%dsf zW4CNk&@cqWe~%g#1abqBmnA|g!U!Z0Ejjg z!=_{>zpV&S5TE=nT}VeX`2%)IU~HQSV>yOg=)V&J{v)tKwRqFfzV)cq^h$Q}`{PKt zHF=OeExbhTWX&`BnWm;E5^ama(BX~?C%rqdFy-PkL0KkkfIpO@b|sh zzNx9TfpSyd8BTOVmh3rFa8f}8vKVF=fMh@|P%ySwAS26-ihUMBZ4y4WGHptB+G(ol z`FB-&d*ra^bT}qX$;+HRJ16ZOMNpAtF$#PZ#aOXQu!_2w0qrNA$JbSWIzC5V6vcdA1ogJ!$h0nFm(9pMI+{2 zKdbn2UB_;io%hg9XBJ<4*0hYvI)=2nugY7oPjZz8yby?x^f9-?lJk z{-POKKk0go`)&6j3mBqiD&hoQk8Pj7taz_DBYyutJ8>OE3O z@&Ul*vx zG9oWT5#4Az0R=e@#e^AZcNGp5Ob|tH&1oEYbE3B^H(x{-h+;`xhZZn%=Hs z+(bVLhM zQWxsBU(Y}{ancbv)?CZmtuO!p;PX(2LY+6YJ!;kZy+B?j4Zmid|KjbnO~-s4tHYu1 zf2wl1;{2rZnnpL_l*-rEjzs^Z+fCl9_(B? zrs#nJzvmv6$ZhD1>2uO>*+NFqup`^^Cjz7i=quY1TZtjN?@zFG|JMq(VvOZWckMc+ zIr*p^fTf%FHod9fYlHeB!N5#G*WX>3du5_caTxrxb8Aaa_zE z=>^kWla`ztxbp2C)&H&rx_0C-i4p6523D0wMo*`X+W$lvUSHYp{VnD4-D~CszI5}& z-futmZuD=*dL2v4YUcs^>pwz1B3% z&ImwMlDV%rv}(t`@QV1@j=kY!tYE^XiqJp0p4YN`6`yUAORJi~r2z2Bmf+)Q$*#%k z%3^Ol{Lk929?!L`t#2;R&&g=WC0djr?TFb)k05Y_VePQMNr0X{QVQ|G38T&v34LPu4Sb+U4HQQqlO3bLOIXzDy^FpWL}R0p_)kx7-~I7%oaWg0$<&fBeN`8Kv5xfw z1B87Nn@``dePW{Ra2VK}H*xq4cP||Oc(PB$&Zc1O$_G}syB&)kSl)R* zE&uNsoFB+TRdoz!|LRQwfd5@GwR!FoPEFDZ@jw6E{`jNsZodfte!O_n+gHsO=l+W$GSgFVE~x+jSZdWee+i%IolsVT_}hP?%bsU=$BjYf2NFj@B%~mT9)Gk zbV4QrZi43$0q-0igbF($O#-V+frlTefiKAq#SIWp(;hRQdS>hH?=2rb{ zukG1$%+30adJ7=V+PcuQD>b=Y9pq1kLV*bnjwrZ0(RMftY^LU?d~?md8gtrzulU^F zrdHP-7f$M2ssGPEcYK)X>GTKim#<9aWowPnlJC5_h?5#{>p7#Jn>jY;oa_ureSW3f zyzqCQeDT~Vz8iD={%ipF`HLIpzqQ)nG*?=;1il|VQT? z+px`T+_fZkeScl=(hWOrU!(GegI4{sA7GV$C?oQeh48XASRn?H-G6@eOyHNl%EX*` zw&a48$W3-@cYI~)=rvc49r3Nhocg3=ZeiXfH%~74IK$(JBRkfQlL-vI16c4*(=77`^{h?pBzT=1v8G7=S&E^-0J{ch5@Kv>6edQP&*Z zxGiYb`g{_q+wJN+1A#$scRdg77YfnbWW(NQOc80OELgDJ;H6oEPY@zkVe*Yt1NKY?Fv^@?3 zliKF!_8A2kqwZQf=`{dYTOWM7%gf!u@UNHF{5#W2Q~&FN$$uW1?#COO>hCIVHa-A= zbEfz|_nXDTUazPm>}zW3)aWOWAcm{!d6+nUe@XyYzSerTBwHJH*Y*DU#uZW8qpuqM z+MwpO9eejJWAnN)l_P^Z(ATH1AizV2z9tcVEd;a5PUVo&js}bwuj1NE?NIiZF@9JU zLrBamPVzl_^Q4kb7L6*rEy0(N2*l-M3h$kqk?~Q6N4s8H&^#Jp$}At2Tjt0 zbVN1&afkq;&Oqo%^`w~m2|$p5?Sl1c;-$-KYeUC-&f`+|FKudymgJ__6f!OL5Ar93 z-$J0s=Q~|$+Or!%AtTZDI1DT*+VT8IpZdd$WW~3!N`Lp64|jec{#umOCYMK^vtmo# zZvkLUdE?VFM`z!ZmntT|T3YwaYpeGBtf@V;Pmm`g+wVC|suE9sTz7eOV`xkK9BC=a z#HuEJi}A5=%v0;}>z97ICHQLqymm+E@$4L0oSP;_Z7$~zm%dlm?-R+o`j)EX zyo~jun667@Cm)~_0^lN8y8){Spkx7Um;!XHUR@etSQe09AThGY1KrS2y(cJCP0dg7 zXbUE0r7kW`P01OS2_TqB~q*yFm}8j=go8D z^jQ)GIY%!*DKx;?6-MYe39HNk{6l;4kF#3?-VyZJ#~XG$Sle~LCrX_*FokdBv zoHOR%-=8=7pDC>7qKiXK#J+$ZNYz}q`^P9`xDBMK8kqOrd)Lg%z3+mtIaenu$=x*j z@3~_5$J4TMve9MUWkB(Jfh1q|MnV0_pVseq^;Ly`(&pp?bcXLdZ4%Ka6wGT^}2pqlH~j7x(UTEUo;}`(nMcQUotB% zDdVy+MZcPn8Th0i;JwqQspE8=k)P(m{EPg!Y$0RjB*XQSz)sOl^Z9H+Hu2# zk^j1EOyMnwyO`tSl9J)KUq4~wTaz<#cI0~9-*YKqgrPH9>w{Rd*o*6KQgPlHb~7J{ zBj4)>IwpSru^o28pScx7yVUOh)@zJ1#yx-ESa#fd|8e@n0r<_vogc4M@VmkOaELnr za}@W@zb?u@VGmb_fyFDUD}EYmw?N!IDR0@P$_Fc(T0kHR08Y(F{&ri~#3S!)zpFNA zRt-;21%T8U`5DD^VXO9$cgr4IzO@o(kIeaXafbVbs$dLnZm(_p#Vh5nm1L{P$w|oq zfcH1lJzN!xfw_A~Z{2p|@#e4zblg_+$7G$gqt>i>;Kj%jo6F_)Tj%HX+T^D{SY?F1 zwpQg$807bPzu>a_2gKfy2)!6WtSoF-2z30SnC;B=j1(24$Ef(~O)BpEwp}%#x9ezc z2*E|7#G@*gOhqh&9E_F%gO5KJJDJ#$z-KHgrop*b4ck{57c zPJT{C^+aoYI4lr}93-jTO$r#)sT61cKy|bM`AONi6Gr+*6{V%6e^yz$0w<6swpKNI z$B(?it%_x*8ls5coS36=Np=*DT1y z>QZ3&#|E0}V$cnSC3(Dy#Q0pF`_??aw|Y)a@*WG=-4Zk2tEg*x_S2@Ow!~d2)C-FX zzLM*AFYpR6o(aPVq*)e&8DJI2Pjg|~A}{7lR}k>o6Mp=^qlKtL+yAXFqAyBNDu#5a z-+?F$eCh^Th#z`xN5z)IzvIa1)8FEqlS^h_Z-|eFLb4D6FqwI2Ec{i+2{`$x(qA7UOdeNbM5zDTAvF5zq(>tsAPDG4*rfm&AjWY z^9p``-TmtnbW{So{6kwD$nrMg%DeX^Tn-O>3ISq0#pSsEnr`rh3YB=`x+$nRRXnjI@;PSSW!FijhQV)p>hSN*CkiC#mp@R zc%L4%b_Hc*Lvv+gLtpI=1Hh^2>B)f<*EGN4I^Cm+aXv+v98kmvizvgg_Fs(OBaoi$ zLdj?a6UIp7WhqDr5KQaXCViko+Lr;ds@=}?-)#bclVjB%hX8EVfM*H!HMB*4^-4uW zkFw*(bN)W%(MctLn{S94RSXR$0015dwJ*MBZ}m$FHO8S|xariC0*OEAlL(%3Rn_Q1Q3ldcGXxY-wQN05t`}=5#2&lT@3B* z_6dXrkgdhS3dkU^9%F8cNp1{TR;3}iNlFezrEDc;BPP)TB9llm05Fqq2}&hmO%Y16 zN=Wi4O1@i&Y`-e<8SqPn2SmcM7_y^2%HtvA&|1A{5{mq=u>VOmzQy?@NXGqQkFRc z{$BsTz4MN34*>uMtG{^VD;WSTn^*GA$))K({<5NTn+M?Z znYmA1Fe~qJZ@-RiwIA=V?L2+K`lh$uxMmJ}`@^H)7xnG0{QL9Db55I)cjM9H-S@ei zK(RY@TPWa%&YRMcofz*9QZK%)(7t%!I4?+tvd_iN|039W2APBVU&e&iE8`$A7qHp-_1Od6( zjCh9xcY=llH;~|xAV@!a(2rg->wwnUkI)(c%EGXrGgedj?hHbBPVp-lSO#46XnEyc z$zHq1GyqYauW0VfDJ}WsSpwc13mpRkunQy}YjNEDSYDR!oBF1^M!HTWdxj%Y;|}?{ zufOTWH)@Vwbj6_?qvgvRdj4`$Zpx2iMPx?H3gTl!MA+zVXXaD>2%8PzH-F;u3N8j|@7weB&a$~CJhT}_@uG`u>-{m6r zvWm`%+OGZu7aX2g|%y?bqP<3kU=mULT+i=NHvj90U=ty=e(C4)R-XYJy`kMAHaa0Kgk7-229f}`YTf1u&e=YzB4x5sC2kF8}Kbe0ta!Bp)3Zpbs?w+g&M*Y*swKs{VZd9nXK&@VD!ZF1h~jaY7VK!6Nz-+&KKf_T60R+j$NIKokj4Wv0_Uw0qyxEWpmrxhLN6 zhqG;ZLktJ?34W8tFQje1DFcoc(a7-8S*rl~tz!=#Q44Iy3jdrryA! zHI?meMayQ6OTBnvTA5^tjjS+x-ip!ax9+QIc}Ow9L3uUt8$6| zjH?eSns%m2pBL!l9t#HlzJiQ_xRPR?2ze%8onnI!D-0R1f9Tx$Xkf_o=z!K39{APO zVWWqn1J~Ujg#gq`z&xQ8IYgA;U+;10oqy9al7hY$Az4el+s-s zBSFYIGLheqA|Qq^!)C$T(uyZkRqI2m>=9vVsVqWl^aYcJ|E|ue^JZ#qW)V8MaBHGYu1fhJjV+W+?8Ozi_9K^Z zy=Q0DqQwGPl@k$l+Ez;s^+0EB+*SZBKA*|k0@vlKgXY5D zL#e~oN2$kf0{gd$?qmLR&I@@7szo$kw(5*Q4JBUVi-1d{K$Nq$B3y+dW6Ws&#?_CJ zYSygl!%0Q<*E_VdrKCjjcjgQ_hh9UaMyU3gqTwwt_m+~oE^92NR@dXrOl%;XpXP>R zew?-0(!pD=kBp)s69DEZjNZN6FK+s**#%;p6SOa#`%>5~oHrzKq^+h6JoMfx-^bj02K@Q@^_PKodYgC zG}&;szW9Sujw0M9FFYR=UnqL#aA$P+^*RSD`fczoXH?;Ik$Awkg_!U|CnAikLnmH;ETt8;daf?AP_DiUQk3TLy z!#4fGmID&1GLv{$=p&ec+kgm2w<|=moT`4kiX(g9FJ@OQIy|;L8_o9iF5^j*^)>`Y zj$7&n+^~}7vK@3{;BHX1i*)smw>r2m^H*xN&DI6mMI8OT|5EVk-Xo?+P&+7{T7MB0bzM-NQ`O z^#M$-3>un#e(8uMO3Po=R;0tM=d@O@)h*So^_3dGmVJM^7IM_)4N0#0#(615bLj(3 zR0O5t1;)rjKY>Gr@KLxVLe5@cF^t-^h-v}%;4+wmXsW@hZ5get2a?MJl=~Ui%1x#P zz)&a|;IvM?>)1GmeE7!gUso!wi_mWVHQmgHlCxLZg{6J;x^H@u*x0XK2yIIw1q~JI z{PN9I|L8bFLq`XM?G(&4cD`m9)*p7 zC9Mzl?Eo)>5taZfx_VTj?u z&`AZCM8Ae)yPlTbR*A)fbs~2!@Y44VB(TA1sFwwaN_ee-rTv=RE_A5)){DQIb%Mehf_6Iqz&6 zshEKA#egBPZZYWfp4N48Fi$t9TQ=S{4Q-DQXT=06);n!@v+B9~1EIg(*^9i|?~zurfnaF+5#u9+pZp3hFrXR6*mBGovu18}j9 z9bbnJPpB&F75dFv{hQ4uWQp!T(a~l3^S_>O3o+jz?2&@4W~^w#9-8oyO5NG%hi9^Z zXg!0NJ^2XI-20*qcE+_NTOpiuaWRG`>Y--mxc5i}*i~4c;W^Jfh#N&sC0~|FL{R}S z+>M%)a)<0#LG8lhw0);-l`V%OjD;@u!l_H}BDQ+Td;dPVdZGY;I33@YC>U|D$)^^- z5hp6mfPdBfqWkB%JFdwGq!2F1^zhbVF}dXzi5wOO$5-1JOoR3u?`b&AX!u(_T@wcU z4C9}@mFJhItf$&uYcgcKU%#z|&Uk8h00o22ej!wdt>0gK2&a;ID(QM&Vr7$FJXZ(N zpF71~H7pvR`u6*oF&y9W&xgd(5g{^Beob*lf74dE-bU|QtowRc?H5HHi4kLCNP=x| z!l*gVVouoqyY_E29s~&a7r@I^;uv?Vw+%``VIq$QvZk*_1|qDK$Vak3^Vx;bDP-Gwr6XT%=j`*_n_f<4A9Oid1F zh1P?B3pmx#) z4V)IRzc>P4zwTE+RKYux-Ah2<=4?l?%|9VDAdnEdZuR*sP&+2-7oBAPFC7z*?uaUY zSHF2}%XYQggJEF{?Js+i0O0+lCu_7k}%|)obd{nvQ zRxWt{Sl()`G`;oL+H9wg2OXz>|Fz=h+!hKq$G(;N+j1~FJmA*UBUUsK;%M+$`ud;d zExqQGSUeC^AZvZ?!ul#Z!QG7J}D zhYFU_L9z9}tP18~!ZB;;Ifl`gpuH*gJ`0I;@nc&XAD6s?I)*z3pSjVRk6&KKjgjEb zmYyfx6SMrj*PYq8YtaolCWI>;`3#La6)qYLMnd_wsR6h);*gq5iR|;^&i}A}YWP0R zqz|bO^e3+>`FF3G|s}X&FZ}LfdD8gKJorj@ZrGTYwI>Zj3o0o6(LK;QJZ8}to_?s z)2pxNqlxqqZrtiVVy=^m-T<3GtIl=*_C;9byGq&zF+hS3dfu)+<#<@bVpS^EVPe=u zNF$V-LM-xZ&+g^Ac=jS>JtzD_sDg>|W0#FcL&5WTA%P|v(G&?+n7h0D5Si24M@!Z` zGy$$VcB$PbqdMZ3Wm)Idi-VH-DCb{r>6IZW>7dOK)J!jWnma*#Q227U-FJnbDWO`Z!9jJ1}h4E_U$YFty-}WynXQrA&N0U0@!%TV&}UtS#{AX^;+Aztc)g^fNtj9RX=^J-krBd1{~1w5 zQ;pMqNPrv=2B-$~2U@+;#`m_sVAz_-i5+Q9cJCr!Yy2rq|_ z05gKKuxAtq-kqLY9K20$F0*Vb;c`F<6o8v6jG{Rz z8tGV`(qk*uvHUt;+u|H~QwK3|`k;#drKXfWBbF2ym9$8APz@f@UTz3&jK~%=B9QD? zrj9J#>9?*7;l~EQLtkuD_+bz8Zj}CDj0aCo-P2+YT3(}gwHgYb%_;pOTQs$?pzJ=e z!R+a#lhHvkHTe)JXYmVxj{DG?{%sZe5)zHlPU%Px09>S{A~ZmLCcFM+LpCXd@_}>W z2Zj_kE1Y{BLjET-Zxijfc(QKB)}j{tjV?^(Q|)uykhF2pv!tBM?dYLos>VdytV4$Utp5fU) zg%9%nrMTofG2BO5?l|97u8IV5}{)KD82iH2etVR4#o3d`h#p z@$m){DgS*?o4oR=tEq2kApqnZKV4)yL{JiEgt3va0Wlev!2y49F~)L=96gOb;UWN> zTrB)ljLUS+EZKX{KwfCmP(GMz>qAz4c6I|Y&`*$;i1P^n)#IX{ScR>dTI?XOb*7lw zp-kfMPGlXM9$>uE*h^T-ylCrBtgmAmV6i6~FiH4b3E2U{c=wEm0J>w!n^K}cW(~jVfxlce3 zR*+i0u8y4QMM8VucvEr?sM7Y<%Nx_T#(=R4*YzP!Pd5&Z*|o> z|Co@XQ-VrgfDAzQ{AkmX444fIZdV3$PB}BJjXGc}5M8lE-^`wT{K1#B>PntxN`fb07P6#>AjYq&eHi z_M`f-?|)DIPvP8WD=O(6IG$!Qze2-C+=wBZ*N;Q;Lro#E7MTUUxm%UA(9*dwcQPlN z@Xwi`0XAzZi&!=SKaHzNSaaHq7V{S_Es4i?_(1dz!c$$ok$pva%%>AC8vO5&eT@@{ z0pL{Cz<|Wj$>MQ^iDPWma#}kIx2lDcnnnb12tDr&W1uk$_!}cYNc~C<5?l{AR3}tqNLjSIOT@3bK3eue_YG&uUR?GbHxk0aL30K?aeNIb$FFOUe z6U+Z9JE;Bwj1o$)+bf=SoInc{A^1MZ=`DxOD>60z(-Ly#D82@bP6s!TgEHbrL&FF!24JsLVJ||m2ty9 z_1@@VtF4}AJTu{OW{XtoW1bp`p|;^qx5cf$Mut2ro1fG84xNPFiGQD_tMvJP@CTXB z!1GChNT5N8u6&} z{--QA?D(Pf``YAh0E*14R2K@P9r<1jV*s=hSQTU=G3*c2YX1RH`*;SkFqk?@@@ADj z`bMQ3*W8eh9U4@5=Mw^e%I}~bwd`Lc$T>wd0XnryU5*k-LQE|K3>Y0p&K3PWlUX!$ z;uPx{xb1NQA(1~fo&MtFCdHz`z72e|)bz)|R6s`$4tZ1^_y^cU#xhR)N&o~XuTZQ$ zMku7BcJcz((3j$h>#s;i7TxU6C(zd~_1|lRl1$B)SF%Zu?V3JbzA}k(?D9!BWA#wL zt^bUqBuah2ZRMlwE^bkDA@e-fo~zNZd93t~d&UCa#e(Mr;GKPsH`y_db) zqj>aFI|dPsPVmn>{@s@Avz6Ju3`R7-085Q z58iI~F&A#~12EW!Hfj;veJsuLb1N70OXx-sdJzk#-ua+gk^0&N$IT@$!G7tz)n?pv zr!cC|Y(K0BLmvykXzQXwYeB$$56WNLiP@ZEdgKSZW+`+xF&QB|fowkcq=2U9;{^1U z0sR)Ws^W~f64aTx)80U=&K3lScUyWijUO1@x+=V6vomGkbbVZWtBnF=^4+k?x!vOe z-%3?17xzE4-)Y#*@lFWJF<<>_K2BI@Xl?VXdV2ugAi31(tb#V& zF^$h?kEJSQ!iR3JB8z@frkZ2o*p(WD z<^`rl->3%xs>aYbwV}6WoqMvM<%y{g(EY{F_EiiLXbs8P^j1pQA3YUrEMG{HR{kT( z$--v&!SCTufdr=Pu}c9-Bf|?Amb^Ng!2vRByi8ZWiXd6V;5c2?o5i~r1t zKYb$ogQj{}achx8Zz$ZhRWDpnxc+t)cy#jqkHSt@-DkZZeD_-hi@xT`)u!JpTcNcn zA=dbi&+^~6uCSmVdfp?--Y$2CDjZ_(Q+}n9yB_hlEggG^{tH^%Jh|OeYw~r}?jCwb zY;e&S^)~qvc;f7&crB=+#P0Kq@{^tOhaY_|#`^`f=IQQCUna{Wk*Be}H|G}y3mm*a z&z+}%({^?mGg>L{X87-PWp_8@r{$Ll>(>_8z&y$yAK+6IP;4GYxZnILlyTnvH?6j9 zbNSkcU7c4`J9DsOg{pAIXLFf7 z_yO5BI<>0euLmpv1t?kHhZtR5_6Hj6bLqU-pprC^D7dU@Bj7`` z&)Ku!E#gBl2TBebk@RIg9p^Pr=@+rK!x=&>9zaZV_Zp^jT&xRYh)R6QJ)orFIt;7{B1Ncan`z9#z$k%V0#uFCh}z5XU$VjO zL|b+kLBuVRx_zGI!wUc65_=T8FhO-dRa3crS1@LAGMpTuCvd}(3F-_cUq>zuwqJF- z<&ifouvUEH!7?_R*$vJfE9KX6c4iBUwT((*X-RB09qNXEaY}PT1z4>PJ@T_BjDQ#f zX8_(_ym<4c#f(gbxT2l?HT7|5@bYvVHq~BP^nIg(LIwlk-Fv~2tN@IN)w}n^qy+93%jnzyvt*}L--`BA_UYm1C^9&|H=02*L3@(#bxw1P4HYFN7hM<8 zxqQa#Nbf&>Q@y6NwA!`+ej@H(+dYdVuEnes3_|T_mIh4~1;EqO$p)3={-iL)UvsU znF-&HoWJcP3gMM0u_od_J4Mm=-LorRuH6pym&gTe9>tx0or5`>3BL+DeO`h{~vV$bi?*6c&&MVvzkD8a9I9!d-T!*z$cpN z=-T|{J20(e|9rJK{m`G^xZ~f52G#s^KdjYo(j;tF-Eiw|IhCHt*`|}F_UN~9#zUk7 zVY?_bVm;@0ZmQV1h^_c9!=xhrnnCkQH}>G&7nmJa+3Rcs0yk#xVWYof;-D1u};bDQ0h zkUN!vY5UT}zrO8M;b3JegHYKS796OPyn0$7;YHEk?oe4eB#jQbNM8XA2%H%3C-}p> z7Kfd9(dpp&es?M@eQA^8q^Z3G&0yrjfYQA$zg@YI3zP=oTVaAkR>{(K{B z*#9kroU8`BuU-AukrM#m{+5%HP@fPf!hilZ75OW_P>Jl(52SGT zqBIT>g!Uo4Y(KvNB}$}{m;6j{oDBDOExVUtWvG}D1ICwIy@aA0EnYTgwcjk zcy?^x(&r}c&du7mtM}Gw;IBEuLg7lU1zc6oVnc+r#7G$}WQTv@B>i(6SP>FfoyIt=!dgW)qD9Pi|*eN%=(g~~B zvw+Ml_Iu*y(79{yd#j(uLO7#7P@#K-LoHq<+cQf8P=^WPhV}IU3#hY_=}2h}hb6Z6xPbek z?qVVw6WnbW(Vtb11L%4_mVvu9Wwd0E_E7&_0aX>B{>jx5I{=gWXyp(%#NPP3Rk$f= zLDg3EMmr$w5I18@wGI{cT;+{U-aNfEZ_f-;@*!$Ymp6ato)I0Po7d6V(?MGz{tLU? z3YL&D`tD7bdPIu_@uM`tHnS+G~2FlQ`JG#-CB;%q$+6a?} zJgR5K#2$It&?v+WBxn&|t((}_<026*IX-Ns<9k7BpSa)1p=FiO-hjqx&x*uCpF(s-`^SHI5VMfNj4 z8ja>reX3U=9|E~yN@{e>hL2=0m)@Ja;wpjH*9L$_Hi0io`ipmi?tYjQXe>zeJdhl8 z?l&Ijojhfq^viEMT(R?abV*ZKgY~jGpd}C7cwT>d1#i5mxSPu%mLqM?!N-;h9w#mF zVIAn$!l2$655!C~O&QJ}|9`*|z}vC1=%|O*`ivGIW;AA!F`mW7wjontX!P`#?)#zz zS^Q2j28;r6O=ZcW(xbhi>AX(|SJOXKVr6wt>&5M&dEde=Ro%GxRRfgMcCG)Th^tL66fD_tH~{i(mH( z(nZ)v8RAMzQyvXVAr?9u%~Eke5cCOJzCM`Fvvu&nMEWKZrT2W+%B!Wu`&BhStBtVJ zmS@^TIV=yeA76*L)ztCK`-Q2pWOcQkZ}Fw^yTRB|N9M;?cCd(A36-3`B{=yowP?~l zz_hjk?mlu4KbsDoo%x^ zKgNgP4`&zf@k2OyOYWw&B`m-K%Ha2X&{a|7m5FlF#$~;3ve7DGDt%2%Yz9qe3V3y7 zkwqB55TXdmSf>}JTxJ^$N^H!%Pm54G<|y@elHA!`t2?#MI&F;&9g3n1?4TeAxhwEz z=nZzO92<4qrC^noVuf^32*NPnjD_l2&&)N|!_|u$1gL*FdbQJWiO8w7@q;3ULc&0y z-v_sGDMP}zO%bS2G&@P97;{oSq4a(u^yl1aks_UgaAJ-2)Z`%628?w9XxlQ~mNi|M<9JQ|b=s)a-KDJu>?g56 z6m6S7N-x!W46FK@-e+G(n6)CESFibYoUs4Q7Z)>W_4oPMFr->VqH{dNKYX+J1f*hu zkyp(yU`_bs0Rwsv&0D_kPPAW7yA)>e&+@Q%_I`JMBw=xnvf`uI@bj8+++<$Fjl`G^ z8wmxAzO^=D+<4KR?N4Y};%bFjSRa3|e)sjrQo1I71M&v1Y^#$;tKB{m3={9aLQ$GN zP(J9EKjW*lwQo+j?Goa59R^Z6hex3gy|q&|D2M8RU<4&dw7;`I^~Y2$r&rJv9a=&b zp~Rr+ku@4*?hQN|CJI{AwfuDd1zaEo2nPPk%bH#5L7ysSjEXBuI1|dzMEyI4vcD(n9EjdAGZgFkd#ltA`($R*@oeMUMF+5dRvjby z8h*ct}F_7`d)H*7m1!LxEod*5h^JX4qFf7x^Jy> zsbL7A0%Z%%6Kj?q;-6A>`PJud{csN$2n@VYrpP|L>uVZK1|fr|{MKoJG3p1+H_j*Y zY^RlXBx$4R^n#syz%d$`Y%k;Ox%6G$MuEseb8^^dZbIL|(yslT=@lQB={a z0d)kgQOW5OW+*8rybof7i$pDjZtttD4n^oD24Zo*# zh!`9Y9EF_`(H{vS({ov}JRBM%#X{P-5ZgG}3kEnTCQsNaeNHiUXcBd9*zOEDdt&;bq(*-k2v{(PK=fXR(6Q1tjDYa#X!)}x+ z9aq&N5I!VbYBeC-jF5^XxMy3Jn(L+<``3ms9mN4{d<72>s4Wrl79dqat%ikR(%}I> z(VQP=FDcQ?lV})+K8~C+l!*Za?@q;7@B5ZLaV)_?A_;)bebJqK824gRw&wl{dd^OC zZufuU=Z-1-!K=)@{?5P1mNV>w(fJPTw0)EXKjiVhw2=}H-;!4IF%&KPna@5aZt*PK ze`{16=+@&^yuwHlIHx}$w!DGhadXo4mqRwt=ujwlxcdgBN97y3Mhwp%PK31Mlo4W+ zQd$l)d`_OOua{VAK2{!1|0oYdDAXX{r{>R7jibZ^p%B7fW)l-DK^t2$Gm@+RssQEW zXTk$9OY2gSq+~)T?T8Cf5b1QvPYn70maTO+#2G}NNYgapbd2lD#cTgcMi=f(CM3+9 zxgN-&V}?pee}d`U$?55>4iU-GS+d`#Bj9OZxQH6f*Mb2bHT`e=0E*P3y4jeQR|h&O zJu+jGGING1E3p z#1HNr3)52w08f1Ue}|Y{Vt8AfVfFR*qW=-o)3;3g%x>_`V zJ2O`T0Y9X*G3`#SgPPsL{9wm&rTN+36_;lrwVL<8QaBxkcR=U?jAnMDlOY^oaU>u$$I=|6! z8WdLYVkhb$qW7hn>Y;S0O~Hb#QqVD)KO}U>&Qao(Z{bQ{DNkBjwQ^;}@JISh^=(M3 z%lr{|=JS7E@{n}@cw=eyQeJBPQ2(R^;nV^hg2?SIXGG8^=z!CYpRY6DfFGFHvHv>) zq?bQ-Pb#NxF@vNA!yri0e9|ESzwvuQ!ruTIeE=eogdZstK-ma5hQ2D&IeXx4Vz_KV zCn^BV^WzK2BgWzC2f>3)O)*iPN56X0(~P4XloHqvjs4CI3>p^Co zilUYJlV@IzbD9C)_0;w>ytpazC~h8czB-{V096GGRTiA70MC~PGcyTH%6BXJLq7UZ z@OWJ6HW}x~Rfb=oen+jq+%I<|R&+rLqN#}-sj4_7oIbcsERvKcfM*;W+4CI)uOgf@ z9!8FZpa-Iu`;!34-@o!|zOj!PeFJ#bI?JLMR&}h_-}z-$V;h#T@vA+r$$T7@+PXSKcW7ro zgK6PJ#@E>K>NnSqirt5%*mlAvi{pXc2mS*LzkH?40tl6w*Ov3{T3R+nKSfZQb_Kc4 zcHD+%U3=*J?q$Xz+O6i5RPr;)_xNiX@xa|7YClRua1~5Geo;-v$U=j!m4Jue1vKxD z*gduBR%$9nB;xW^;O!mvbxMA9#gaql1_Rm;+0ii?W zf7*r z|Hb{EGkoas%^_3H)MzNE15lTRu@JG4z)n0+!bu)m&tdX2H5{+Z8+)hZus1@mT6q*2 z*i)!Ox?70KSbq*1z%g@smwY4w>REYK!!~y4eUYTD(m+lGdnt@N2t^|RvYm158({$Ry_N*S{)QvryI2=6LQh-ZDWJ-$dKOfMEa98ghI09OubWj zRchg4^Tsp9h85qd>+9XXCGMS{iGkc0EzykB*Yg6Bq@<|q`n1AKCNRJAsFW_X$r?e+ z5^n(Qp5uW=!SiK&WIRc8Lc})o#swG+PGL){-;D9*Fu3pxh$!U)p%G#%feU-XfCLvH zq1xioMvhL0Hz)5m6v1uDef_<))rSW@2CNBvF`4_qg@4dUi^5Zb!l1&l7f4H1Mfn&Z z9eLX|@mHG<-PJjgxSKpq8N^6%x`@xcW=|0D^OsM)&vSo4IgRQVBKd#7g37|)nfnRC zS}U5n)3-Z&?zqAoopK&-q(8=`#x*P+#-1NoV^J^=fM1}`@dfNh_z}hMCs}iPgc(g5 z_0_B*`wEQiuv2-Ga=HJ+4QHp+nnbAnuzkRKk8d;XLiOUWjZ-ZO`i;klP_^7PCi+w= zc659!$}aZ2rpuCq6F-$>d?#l0iq_R6X!{?vfc8{Gk@_M*h5^eY?sJ`VzKpwpMaAGD zMSQg2E5U#yLQD%^E_Byx6KsQ$LYxiUMq!j%JG{Fm`2x3PN%_sk;UJGg@gyO0EjM98R+`TAEmN%s$zl0#OY;ALM`qlo z7#)f6PJp2=Ij-9AeU0DzK6W)p0zTHblmA~FqSy3VAKi$t0CuP*qN}yLrk{QzzHg_cxk+X)n z6N{b(c1Q;e?(_jXLKcwyakvB70eSd_CBfyG!MmRi$x8t_#K!nfM|mE4BMt6jbR7>2 z1t4P+6O-ypF0v{-#nCXi-`a7qH47gw9}vr^mw`@WdSq}C6*ua;-x9_#b|_M1*2Z#B zbSP0!_Q4xD!>_5?*uTxyp31@?BkuvjKyrSbe<{iTKO)$kDMHLv6|iT;c7fL+_d!{z J;=Qr|{{ba0p*;Wq literal 0 HcmV?d00001 diff --git a/doc/img/ghidra_console_output.png b/doc/img/ghidra_console_output.png new file mode 100755 index 0000000000000000000000000000000000000000..c40d8811981385bef408a4bd36c72535ce0749b0 GIT binary patch literal 79236 zcmdSBcT`i|wmysn8;S)50Ra^O=}PY?2uMdjdXY{D5PFfOA|SoD1c-EyUPBE6N)Ig( zq(*9pH0cBg{5G$0&U?-+If4+?2aKKJ>)}CvvIiE5Y!D=dUS1!?9A|WBUBLDoE zItj@+MG}(JYZuM|zd7KKjs^ZZ<*Y6zMN-^*2M_#k*6OM9QxcN0NU{SHQsC!{4$pO+ zNk}M}j{lvKSAXz}gybk&{@GJa52K}t^C{n+?SEbi`n1U`^ZLc7cNezL=@?zV7G?8P z?G(FC>Cr9Q5+s|93~AXbDt0#I>q2U0Z=HRLH~gf@djCR;AADq%3xVK=O|b9p`$~9q zT4*ry#+viS_RK0ODvGk5V(v>~Wl!Yhoq-A3$2se{3(f!o`u*}$R*GlBs?wMRp8STy zQ^ps3;pC^N7=uRL!I~Fmc+Xx-6RwG{6#n8ArgTs7h{fu?p!vgc@92YHvQ=Lf+&^nP zE)kzTJsCK>HEOEYKcOWyqM^+m+z`cL;v51FNT%8rvsIxlJg_#EUcfm~G*cZN}GQ6{K3N$m*gy z^i>qTr?l8V+DMeY3e$KWzTeb~xwaQ@LF!lM$ZezcoXo2->#ej{5Np{Ks@zRg0B4va zUEGPbc0`otC9LzMRCln4dsbXL9z>TRgzL+@2Hn#qAyTJ_2PXCR>u&aozg>W`_#|wu zVzHMa?+C|$c2}E@ENSQ^yuV*Qb99wo%w-{p`rM(US=(javrZz;4g*%f?DwRj=R#+L z1V3@gHl0Ze@m#)6^-G|kc$gCXZl!vBjayp0g$A{ss1IwcBB^t<-7V>}R1rs#PzmFC{PvMWSDZkrd@OU))Y3== z>RJb0iM)Eloji`!oceqke~;1sB}5JX_Yh6~XCZp+!JYWga9h#1cE9KWpLg{~+Tez{ ztoJC^rE|P~$(yCZGT&>C7HzMj8-KWa7M>D5T(ktzgjShgZl|c-_7McPX$S+xxsT&7x~=RBXiVrQ}joE(lEW_DM;($YrDss z3-;`3OZf%y&x|@^ONGBywe*mA(F?F#)#`;Ykv}dJ+0&)CHhG~S%rBHaK=_MILu9nj z@Pf|xektjUJ-cQ8?Ab?8Txd~z+SSMNJ9E!JwrFZ|26ba6-=>@9$7n)hD%sl8|5fV2$uW|!}rgBnFlMStpm#K=&ovM^E z0`mNQK=;SR8`yp_Vk zGPQDSs(#LEG)-QdcV4Si?#Z19K=t6JH&prIlvZ$430%t5QHp2Xk(uc0**wA>F^_)l z28VIScKL}q*KE&?d8h3Wt8M}g4hcj-`C}Sg);{#p`} zmF#gC6O&>B->nDXH2g6$k&;Fsx7e8jF5Tj}#VEpI)KH_DuP#F)Xm2~uu3el`^&q2p z?7pX5cLFC`@&h)2s=8c)N>Ag@-DYndKZS@(hj#?MxQ&EB(VPCh!!toBt8V!D9;>5f zKa`x+P~VhaB(zU5C^D(9xm6C;ZrQifCwY_UQO}ccW%4gqAx6&Heo2^&Z zC)}}}g}N2yhX;gm#~E3|4%RQ*dLYATP@W~(lftAej2h2y@-$K6>hq`@MR)U!n~<}8 zaIEJ0gY7X$PR28KrAklyQ&PhZ_o*2b(b8@0ya83z&wkhe>dM8t38yquJ&~^3HN4|r%d2Pq@ z-cpYi*ZpMUE!3=qQcn`5Id}`TGIOZshZQK`-dYwiW%mP6r7mSsmO7=cPVtI4bTHhk zzgTQM&;6)1*IsDoGKLvY{#+sjXJDNZ3xt-C(^+nqpMZQEw1mSUx01A~Vu zHsA70_JmjsYD(`2IXpSsow=&pob2uNUWFrRNLMq62J9gjrqj35Cr$`4 zCv!(+gov_!y|}K>N(8obSB^4FY4rSzt58bM_+u^#POJ76bgn9*?cj7%#SXq^CPERL z%c)=8vD)iXevVULcG#q0b=)M}B4=^frC%(IkpHUr9W&hKU{Qdd%inQ3JY%tUwYy-b z;AQNkTWndlAyA#Nv5V2(FarGO^seVP~w>BD*P6FR8^iYMBY;C%LNg>n6vK%Ti9l>8FD7%Wi+d14|@4UD0d`mn`_2GblHSYUA{IU%ZrNV zoT{{#@aXtq4i+M2h@7|55R!%nd=ZoM{-nD%yc*C<>9;m9{uUH=P-~qr=>UcCfLL=35?db&xVcOQk?=G9^Kt`PrM%;PK0Mm+2vWa;k zsC0OUGu{~4!#&*?X#{r19SNsz-s}68!;vVXk}+UAL=EJS<{6<|l#0RzPHPsu>X&-H zyqcv|q?dy)@vy$s!YIe)C*F7@@#{G2Euy}DvxbtnLNO1Z+kuJ}nV+_&yq zzJ?r-uws$ooGC-Ze61pAirXkiz0L&$wqN~18$@Fno~sbgmh1p-F70pqjN~tgRU|N_CjcJyk91fIU5mfYvG#BELkj3857vE06%Zk0_uUR8#jb2F2)wfghc*+31l*hFq) zdkHY6u#=|=>6oD$iFc>b-W#w3nG_m!eA>@ZtyrXG5ipGOO&LQY_?Gb7?VX`QnsxL= zO6t(+ItVbZSghaCM4{Y_D!aE!9^}Q+WaC&5c!TXu=lo^&A7ff?_p>0{3lgBoftmKn z+-Zyik+_4!jMs7bje<`#Dq}ZGH~fhgvu-g#ja?gQqrS`_?3G zEC#AcbvfEJuv&%pB6<*!P}RyC0uDz4knL4?v7BTT*veKFd%rAq4F069F;+!{bz|Eb z-aj^G%Zbmu#V9Z#N#xKi|MDe&ySq}PL*O?6e4{yshcV3?K5E~8rN=sbuzQ#ksTI6{ z%Yzt5?q59wOYD>HO70&Cn@UtOB47S&UxqRDBDhlmT8suxD{_9AZ1QW$f70JYYGur_ z=TbwfS5p!&sz9b#^+<1sr}By6%;;po zHrBK$KJylf{SNC*gkv7*=h1_h!8u9}ombnc?B_Q#XX^UgG?es$KX$*5$*b&9sZ-VK z+#WXe%U+GmDJxR{8iGmkg0fT^-_7;}1LZX5om3y08@*nQLwbJF3n*2UDc4P(3Q!t^ z4vHfW=qL~nKgT!0-}kfHB@bk;9b$tva0@VdNRtL23<4q-S58vrxAk*~cc#uya({kk zzB;A-LtyiyG=W{WQnhv~^)6Y93 zn@%TsoZYraCmj^<>6*A=HI-}6So%)-Xc#|mX$bqgGKF+WZ}%q?@W9HpBbDlmIu=PP zXbDBzUW?OAY@8LbZHnK0*mMVJoJ*YMy5^VZvLV+3UhlUN&dJn-uv~G@b3Hrg=}$+S z%=Z4irjyKQnm{)t>JYEbQ0>8nIbPEq(-V_>x2Gw7@80J!0EYPv@t)<5!g|{-Vu~Nb zs|vJ}`=IgcJyt^@bMqBWBkCKvNb@oRhyEsvz(HKr-YC2EQ0KGv((;24w@tdA6cKKB z={s~E6c=O=i)9UvZN|6fY2|}zr<*}uZ)AjE#@!FWeFzZZoM!xg%<`}q{%^?L+Y7IYQZ*6?GT1_<|2uiQSryK=x294TA zZ;Pj=Hp1N}J@L0>acN$~{E0hj3j*Y+jyLU(Ds?$w&dE=L6}p$=!h8mEkhY^!9-)++ zJ-HU$3G-%0t3A@ag2>atX!aO2{7MQv7wTo!vM|gZ9q~h-uq`i1Rc&J-v3-OS-Y#)4 z*-32>ok82GBGSj|eo1YV9SzT*DU0uOC+wd6J!ti47N#b>+Xe8JfJ@N6qt^huJ!&it zCWxUCwS@5rB$RNut}dEzx#3efVH0fF?0q;^P(~2@w){m2e&F;42>O>U-Slh4O_!FV z#tFe%uPB~$jVwjuOTLm?-E+&EZ^ye++A zklDaMsHp-bc!~K12&7GUcK?B1#&%~Xb#9%+z8TqpG3nvzP1X_-8E4yPpT6oe9f*6@UIiBrhFue??SYQ8DxS>z|~)Qi8mC#WME=T}LZB;Q8o6CR5ya8oj$lu1YxYK904EzoVITUzJUcb4{8#Y#c1jnOup?%Py?jEbTkgxNx0(Kz;@6Cbp^BeeFhU7@%5qnA4 zBL)N{L1>@R!3~;*7RG+KI25LqH6LL5qRdnVtYnTK%+7(IS-v*OWxeI3Z{*k(U4hSd z(z|L3s_S6~0NqtWC)te=xblPa_3RDKau4))tvAm$x9H42w$}0bbbDvpWSBu3*{kq2 z#dc?90+W>0w06B?q}j6}C7`!ABGYcbMQ7Rjowz~86C+1A-y)x)_tOVlIzhM&wuDL- zx7SAb>P%n`VJSM=UVN`vXE>dxn~qsB`z^C*{l9Hur0)7+NfWd$hDou<3ZOpo6|Rd~ z8)Ywx)luFm_THZe*3QCv1mG<_R#>FZe5R`QBCbDOdOj1SUTf!N+-f5DRRdu^5k*=k zET1D(U?8mMEWPI!&-SwLXc}j`m#b4|ib;Y~u4t7QP3&>=DYNL;kmoj*du~{Qdl=-J zCwck>FE4ovo(AK1E})VV+V41r@l%cmUZEX~ROTF4onOmFwabVIRNIc2hS$!FHytyt zuG;TSeus`!a7(Ybu4KpGQ%VvXeFKv4u*l_@5#?Vi73F~d;Dz=5Hz}Xg90pFE;g(4a z72&UXJo^jiU)vPRdKVqmJ6T|YW_&3kw&OKr`I_q?8=T>5FGAsA^K1>}R`Ep%~Oi58(MJhX6 zATsw>i~??;K{r>0F4moIrD|OYCWRJEciE%1N->$=dIx~0m0mOHBLsVIB{k9m%P~OI zueMF59wws2T;D+?L(VV3wQi(3v|Mz;BwIl}Q{7g3Ju>qxQBac^4Omlmxj6RqvQJNW z<1y&^qfa@o80+cjC8YVW{3QbJll>Hcj6cLxuGqIV!TH)Q(+b+W3QYg5>Ir`PQDp5) zouy87N)v0A-_?Dx3s-d^JU7|rSM^_Qu^kEc?cwEkT_i?UZgIZ)7V^d#8mI2Hz4RD@ zI!jq?))|x?O96_Pyy#n4=O#zj#DjlV)9Qf^M19P!%7t z<&Dyc<1nasv{W5OIWJ&0%Gc<0KgyY!d%9n%-py_!@ae-n*%0u5vY@XxPOd}SSX7r=>uL{witA~G^5#62S1)6_e+_|cG^W(&o+f9IOYk9B|+ zRkj^q1H$;RR7H9gJ)&R?2Sx8I$Spj~W@8>j_L>Vc^eLX7na57gCADnv5Kmx)63Lc+ z7|v7xOYz}9y2ib&MY&q>qjk3iLzk%lOj1YOqtvFL2y6W>)TYz_t*GM5S9WjH zxi(Vk!#oo!YKm~u2;Pe-t!`rbre}1rlgf%TD@w|E|(kc zbxlB+(x)m&C!Wu8vM|}Im+qhqw@epFQtTp@2W+YxPuq-@~L{|hOb zGd-SZ^hMo9CY{8hoTwls(yg$Vp`Lfeo3Nf7iG0zb|4;Rn+N0tRULzsN;$u@JnH53j zWM`kqhqh4=>VlMpii2)t#68 zAhbBBvMJtw~m-bg9fRsuh&1Za^VgT;L41vht-nA9Pl6DW1#>-xlZ?%-X%-cm2n;uQAYE#)vq8b}Z} zd6NYpY5dxjK;?{L7jcWK=oL|9(<*!jfW6pbH4*S$<|@kI-II-8MZ&yfg6$uk-=;pi=TYDKWRs8hKreSsb0l=*8OS`qQxn3tQuN?68R9o64Cr%jKb(9pS&W> zez1j7RitKw{!jSsuHDemHKk$$Km9e^iS5|ENHH5JdH4w3BERjlcIoBgYswa#dsk?) z^oBlR{7l*IKn3h=wZ|?2>YT{|qOF9}nLOX(*DQDNq%d=eY zgX@62p4^qJGp~S4n>#mc zRFkWA_6B~K+YA}aXq2$p1ZQgE)O#>iZ5N*^>YiLvq?X>`VvRK#ty~Mz#tk5B;>KLm z?5ofJnU&`a@3nz~^~4CCG#nBJ#3&i07e!n~V7qG8D3pw^Hb3yH^?0W7_(w{vPf$e8 z;PgfrTvwx9Wq*IQX)Z)1m6vm8(rdN5eznnxh;tu$sjUzRE`B`2u3e;1a`X1V5-)!L z2s5_Yk@VQCr)If}y}r9j{B_crOekgN#LhUl&8~OZcMos1KDt<A)!^?6&Y=SbHX*+ViY*bNAF}RU5h!uUL-Ti9EYua{^V~d{NZf*VKFQ*maao z<2H7u4Q9TCgLl6@bAC1>l#3^|A}D5QE=Io9u#@$!Nb08O&D-Xg4GPB#O#4Q&3O`h&w1@>;OJRso~mR;u5 zGk6sqY&+U8LPJ3SGH=o2RF(ta`x>1#tz{F12pcTS^+mcB7#a!?_RtB;Ay&^ol}(J; z#E)rI^oAE}wYjHyBOgnGy}0$}ZFKJd=&^&=ql8cs2Pm zNp#1Gns4EHZMr)HVRuH=ye~~0GfsW{@ZTEs1uG%}7yU7Wy%Ic(QL5lHsOblW<%_We zE6sMTOw6u#kI4gi1WK+w6_|>x5H~dlc&OZ>-}38pcIx(6@xu23&6uGA?Y`Mlc6x;X z1#{9}#PA#h;EHN_&^Z-utCNi9uO2coDaJ+d_K9iG`^;Wn9P2lgKhJ^~J1Kq-WRaDX zm0@y6oc~FQt3=yWxvv@}ixFti!n+Ba`aP8nz}Ur>0B- z(=iWk)@T`d5x4T#xsGGXw;rzz>3nNLL-5qS4Vu|1uHkQ>}e z$s$8Eig${VZVOpQb)Fd*6f1{dB^H|sf%{wmbNnaMN`y2?=O`tcrXeF`$`iZ8nU(hx z=>4WIY6ySaF9`VMjO&d*Pw%1D7RdlX#hWaTR?QbhKQ?RYsB>MM{n6|{pE)C<+=TYL zVKV(CcpWHef~+G5_`B9*Q(F>OaqHhGus zq$sb-fB$Ef0!i(u|Edw@UvSevv*<~Id=B~__0jyx$AJc$tPk=OELnb0Z#_=&IEejq zvp1SD{|cNv9{3#|3}!o9Q43F75P&2umP*z)TiFnYZaMR2<2Mp}(vZio_B>ZbyJKtE zn1$cwTNF^L^fgZ1-AVsQ`+JP}fn7HuD{V#wY0fz1U=pk3kM5pXJ8k~MDg!sPU!I5;iyOuK3nHP)B?=wKs~pTFFkn<~ zKMY0p)u!s(H!82tKY9Y#-VZ65RpJnnuk~N=AfIy8?wV@UW;*VycQeic?o?I6he)^A zev_U!`B1XnL<&{07YYd+tbh`hXg7xFF3(o9==ugK|0Y-o_=bwTqB{nl{*UQ*+zo_T zHF64XvT3SqFO4t)9$9=P9u$)xAg&>!`ARI!YejevAHsg@a60Y&GNFisd+#Opzy$lC z?EbLjuLZ|x=eWAg#HtG58$f7gV?CvqixkWqUoOr7c?g&M*{5Nlg)G}AXj{F==4C}B z00PVhod7cwV?Zr6H}J}HFke2l4e7D;05DqO%_7Ayg3|SMgpjKFSI_%aDZkChCpPjr7Qu$MGf1gp zS^OAhSd^k94|iLY$XG_YzqacBpin72&4MdeJ=kel|4iIb1f2guR-oG1oErVFK<4~% zA-1&nX39wA-A^EN4#v;7q=834;%J&|QF2Eik&E+qu&igv+H3s=zWfW&oN6_W^Cj9> z9Ck0wU1u~OuL+ZqowM{>0}R;O%bQ>2)1?A{FR#2-sSFFNxp0fS1i1~}#7~Uvakm~4 z{S=!HiOT7pH1d2dC$QMrjaA3%LuyC%xGSiPZgT;k9k^{BJ#IS#HQcFk{ua1F2p2gg ziCt1QM`*-Pju6)s};)_=n?& zo_cNROLkVEktaC^)v*9$*gN+;&(a(y2@NT#je%Y?!<4&mg%Xd&@C7C2#Jwx(g*uP( zUo_UaEMs2Md;dD>*#Y$RIHb>k>LoC*SxM7cp!fc=dya0}Mz5&0ea+$Crmu!<;~q4O zP81U+irDz|`DxBI6}Vot_z4Ox%i6R{0Z=%kZQ^gB7`{#X1B#iKjyr!eRPERRkPy7N znD`jmah=#h+W$8F zj%;>su|$#Eh{lI8z0z@S{ytP2s$jJ8D?MiqE~F@@^2jyyaSc^Nt^zEDMsmufiILy`q-mm;!B8Jf^B(%XmSmzn$K%WmDUvz@WCg;c&FT z(twPU8?ws%`7$$9Y;XG4lzOg;9dEJ8w^9+1flbP2%dK~^u_cUaB6RP9nT=95zBt_x zP7G!8s}rBJTg#E=bG*UbOQGwS=Dpy!?JyPjuodMciP%9|zb$&rDD!M@^v!*K zd&X%%hAO#tvW( z-1RH*QMM^8<?%X&OA&wz|XDG+f6D6 z{1xpBTqP&#vp1%)>xK`s3fLAo`1oNXIt!8Hp?B$!9Hr>7)fzOEy#N?6T}J*FM@rv# zPJIkb_m8CuBBdWWMpDME4nM8ZfKLiO$Ey#BUoS+_ky6;|_k#8;qfw#DU#CC64MUJe zh^`0$kGI_yMIkiv@UKyMr!Kj4s2s;DawkPkzQ^-EdoM+E_Mqo)8^|0EkY4Mc#Zl@d zuT>=D&V*MaDAPz((${R$8t-VQN-g4|(|;%pBsP^DfamI)nX>zxAC+p_2_NxkU=W86#K*ghre63x z(FSa(e>VFzP;@&13dA8DbUFH%@E@lWgvfj^QTN=H*U#)1CgdazcPU0HtRnf{1A)Nm zdrPusR!p+jyT^8OLs+sE69pLPRws*KTXyrF75;7+kopWWIStUu5+m_g=23Gs05Z&# zV~Q+x$@=u2Epn7=fF>L{a{2=~g@lLqtkOJl#P&KEF^F`~9qZ9VR*g2Xfbn9(F{QO~ zhbbvw-5|y^++c)lmbhaz%H}lAXt;E^ z;+2B7q6%kF$=6u&+NT@@-ug)Q<&Tq?PZo-*P#jsD0xsCvG3^6K3H&4iorwtv32PV1 zEdH+W>ej!Gr;ZFTbZ9tXQo#iku_J0RjVanGq;q>&;0I;B#+BCBsn^!K)zhU&!3qw0 zlqeKp9BTBP+E#Qx#aVGI#_zBemj&oun7IBWJMqKsW`hl$yu9>b)wQeME#f*gRk6!z zbl(^xymjpB2$UlW-F;ol+oy#QB~mEubSY0yi`kC6F|>Ozi~8vMJ&8xQQ{TH^7U{{z zM%=z$?qC4JI<82+^0*(sAEk}IMkcs+!?q~{pmvhL-r4p*kdo|8uP&idQeM%!UK2ySv8C;ZIhxUbg^S}v`WHW^EZ-c9`AG8 zi8|%LD_&gY`v=B8TUGoCjRLmc7eWhO0GJ_Qzc<`GSK2Lv$UHeP>U|DcW(VP^}Vxh0204JP$(yo|yAAH3}DOVKw*|H{i^nSGcdCD-1wdJlPj z3;_QNO`OAh-8S7?2D*Of+$WiUmcfLHdUu$eP4f~Af@ETpji{WzajeqtCy4W@(7*Qh zcu@Z8Z7>DO43IH+9T#0q?A)@X-GZ6?J}rq&vZ$myRC`nmXn%ysOeDg~UZ{d_R zT0rvXpkj-`iFcBtlUnHaG?3iA0h}^$ii(stOggPbVsi4Gzvv+eceT5fRm0$Fxe=At z15!W}qBV4w)v&G-|LS#nL~6M?{sv)hv9lZy7Qptiqz$?;ybpNkGJJR+MA32e{^`9K z@$b4pLLznpazZi7&;On24p{xoTlsIile>KbkAL$70B0!5Y_?MH zx|5#AHKVDPfH{<)9BlLTJpM>mL;4uLSWY6myBEs;d|I6f7{vN}_Tm~THm$r@Z2(m} z!+RMg4o-)f*SX{$F97PRR>uwE zwj(^elT~2tiWA=`KNxuK+R5xALL|U50qi60SxzlGvsgmh0Q%sc0Wz%ViHCG|3-C#R zSi>co4BT|VyuJ(l_Xyi#t34ikNSLq&IfI04o4)bu{MqirzOX+U(Q{71;NW0{-VFZt z0i}Id?g-G{U1-?Y71lmYzy)^hu2Gn`0m>{e=Vr>`93$PHPszZ2qN`#c$7X`lbTErT zXAG0Y(IK(i4rqF>cF6}s7!=s4v1(#>@46PFV)bPV|R>1FrLZLWVYNzMt5g=!xciBAQ^acwMc z+q7LQU~DTT3CS}nCEcZ92}8`UuZD6uFmMBHS|DtCqh^8L(9#S9kbLzajmu;kG~nXP z=^`eP-_B~rGKc%DeV6|^RPa{^xb9BURmm6z-`#tP9x11rz~4W%ajcC}HMe zF3jaZn4(YX%(`2m;?Sp;N_9s7x?j)X?g84;E9ScjUu4PxD&7`4MVQCBpV3lGPgU$N zi4TnF3B!608zRky{8s)6}urJ60x+d8aK{e5Q$= zEb#Kf?uMR!H(U&4E#5m-G*)^WD9akW4@uNE_EO&4T(Ki2 znj9TAWg8zI=B$5Z{U#B}o&_1JE*gK`jl%dPH~wmIz+;=>TgI3zA;iuXza#dm<9urV=A|zxC_yR|*Y4Ty9=6eD&dsPwJf1n( zesX{!MkC^q#9>tarNLsL)|tg~W@~tMK#n0Atpc{6{BnT_&;_K)+8H+N7}aHhY4^;V zeBa^65Rv=|FR>CnSwI^$#&3WO0pLxRk)26r_x_L@bA=Bt;(it!1Ps5egarR4vbhk> zaThaVKuWYn5}3gp<-Ujs%F2u{S4sw(PrM^~ma^y1gofg^-4Ja&00_43a2Xa$w zE^`1*$qjb0=$f4jT)t(JqiiVeg|r?5smWzKq!2>IZJ&cjPwmYIAy1V9aDtaptvu0r zW>E2n5wWuhA>#Z-4=eg4Vu8~c(45a*|Ah@>0gVTGj|-N@YrFXbH34*h???K)4tUp_ z3E_N*L+^;J(q>}gsCg{`0agyM38{`{w?w0-YbQpMBOqY>jdoV3{DXD^B2hITghYs) zQmWCj?AWJUA>b?qGQQ@VUdn;l$MNGv*aY1GZw3{RFf_F-BahC~5EnSA)qp=>asc>Ra}krgU> z+{Gbqb?U9Z(quov$2L-8FR4>hFFkLQv+yrE-gwE15C8Ernn<8Bio*Kpn-3bY7xfAe zT{aB!T>O@YUf^%N7u;Nloh!CB6+io2ANA9BoJchDcTn698f{SlaZ^!=7 zOaFCZLNWYhLg|QYeT#Kch-J1s=;m(k{1DBE@(`hm+Rg3$!dgrCenBwmnY6WA3mA6JYRuBs=MgqvN$lGbhx!F53{P>dI%! z+Tl?EX4XFn2INa!BfsUByv6afiHIF-m$MYg_lTjbL5is&Rj8W47p*_D9P=G*$h39W z@wxC$a7mLr5f?Fx|8d!PpPWv)eGVQ;?19F(jsg{kQ`_aIZCh(FQ_4V=zfA*!gO;`|W%kOivhb zq$o=$AM5qqzfgi2g=N2v+rYyKpymcnO$y^Op~GDTz!0mcASLs9xQ9{ai%BL|dChTr zR&1}2+X1S@HCoP|V$=K%=ms<9!xt;Nj8qP?X!#Mh68V|&kjy`I_c^D00f*z@eDWr% zBi%7Hl$qwxnLzr~^HUlDk|Y3~uRGaA(hugDNNfC9vR&!Ke>aN+7&1C1rk zS6M%Eo^A8A`Cn$4$7nhtR)Bhr35Q%6uSL^zU*m|74z`5Hq>`7F!(_Wx97Nc;H2K;K zovE$9%2%d%3SbbxLFK<*vsZwz4CJ=xS6Z7uiw7-TD=REHvkok~Zq^bbM2l+66}Fwq z94HqO*|mFV$Vz^DW2&=YUis#;V+qbsHbKpnLXPp#HL?e z$e(a;bW?NS<^qc--FO%0l*?!ZOD4npdf{Rnp~R6H6S(Z3VK_zp;i1XfCp;8CBP|;H zA9!dAEg%?IwLKd}G>y}c^{q(CfSMS6_O|0yQbiSE)yqo2sU)wha^#gFi*8DQUs7^% zm9{+tD5ouOP8R_7qbUQm+cH!}*5MX4yVIeCWlL3_&axXS&C?Yx3lcC%f!XJZt(64IpuI{-;dv7MZ*N1x6acgW#?PW(Qw zwHX=w4uSzh(GC@rE>8>%a-;lBEQK|I+EQU>N1pfZ&RN=j;hfdEFIsMwDJApFbG~s~ z9)*Ic1IT!H_Fp;IH|q4jC9yOV_|d9Rm!B>H7juz~1AwW4AJ327vfI|%1b_>u{Npr^IuBv;%1(T85vjP^N!H zV1JH?ANTC9>3k=x_1am9?~HAFocc;s6iohCIoo&g_$OuD%=g~fHH(x7nkjoc9*qjh z9Uf4->TEmpzH?ko85_BWKu@&>&E>!#(cwrJ4SNJmE8x=HTzoWR=1N~ntvF8N9GP6+ zYATwsEU`eZDkSXAy5}g@Nw^FbczHLwl`s@>KDdCl7o%5BV_j73gg^e)I zML%n`3UX^X%m_q^Z#{D!x@Ij-z_Mfk61t`L=Qs5hYcWigcYd$ACqJJ9CKbC@Vbne8 zpiX}AVnC4b6aN_kh(=Ubf4g-fZk2qtQzFs6%UgnlW&N_q^$`AqA@)oo<&uXljBL3n z^%3^5Caq~?Ba!Xe#y)o879~I>+?%$E+cMUgLOKIF#t$v~i@C8{_SPC+KjSo@&)25E zqCEJHeUflmL4ldN2qwiu=t)y@J`-T-p16OL?>+$TUudGhOP7DM?D8M>GdBS((u^~0 z;fcP)J$>iULVbkFKgr>VX}9t0;Cq=_k+3w356|v-5X_>)6uweIY2TMBs!i|l<0-YI zZv%fKoN6p|2!ZusaUb_g?1A#@1FO-lI{%gs1W8CZ?mB=f&H_!`7@h5Yq2o4~_3n41 z%qrycVh{h2!)z6|EPvWsrW6&qNP7PE_k)PWUeQ$pUi$EjUU5O=v+_K)IEOn-G%0Iod!Nh5JUT00#Qkz<+#wAiWVsom2^@@d28c2Ar+r{f&VpD$G=@pUo`2#<(qXTea5vP0{U4oV9m;usJ5nD` zK6&!aC;!r72GGerNtfimxzG(rOK#t2RR86G?QaJ56L9+g!4xbxqYvgVOKt=Nd{@bX zhe5!p#v{>@jkEe(G`(}S0qeNL?gGtdXLik~8Ng$s;zjx#?Z4?6uX~By{Q9)i;jYz% z1cvcnHsW2~uJ_8Gvp+aP=n)rPIX$;kBZlzy1Q}O_XmV>QMQ{QLUV*-Ri2J2_n#9~q z-EynQamgbp@F!z72FTPj6QV;NpGY;$%dJ?oD4hv-Kjm!k*-txT)IT|x5Eg%#=$0<3 zQa3sJbBt9CL)m?A`Rugh0tdI1yW$esvK1ABr2=|3pS6MIu>y6&dG~S?*;%s5sA3F( zr&1kr??`f8RH_By^`w0EyP)Ex+=%B~xBd~6R`hAo+2owuj;boK{POhItmn=QLtbI zdKTvIwOvB`*e>q-SyyPFc7P#v#`FW~^4=FhSpby&IXor!<&QdlpVJfSh~jTtMg{^z zB0}tN5i&^JUj;fmT%o@18^J7k&Syy8mj5D3_rs4tF#V zCd_<3MR43F2eW;kf?S6S!#75w68j<(>HQj9ij52p#b0Ym5Qy%z7QF`e&1Lt&R(Br{ z%K_7k`Pjs2AVr`LccqPVstxuIc4PVZ9qkLWhc#mg$LqDv^}x7On_!^80s!vCGw+F? z#8_+J_fD!##`}~X`w!IPGi2r(fYPw)cN8B)#SvF4>fVJ7I^zE$oN3fPzYb=dmGLCX zk~K%KJU_QiZTccp=P~cWE0i8#qyJv#ppi`o*tqJ`Y+quZ*s|a3!!k2QqXrr8`z-yG zS6_cCwrC6DG-O`gEheJ{eCt-ESZ%wz&#v#jTOaJh;zn!adILmX17RCobe>#CgF+ex z6)UpU9dX|+^;CNSoPQ^P=_Ka&{hC%K44Q@sz$C=nYu8Fp8n5iUJfjpNmS<-yJ+5a$@9I#qeMH_WRDh?bmnj|D|z6iD1yjCO&j?!IwM>^M{a7(!vdg$iQ zur|#(O(Fa>c`kyN;MiPjxITd?!hCC(>6z(Dp4tR@9Iu`iA`W^!j+b5F zd$(Wo5256=%bs=Kf*P`L*PJ`Cl1-aXqJOP!8L58cSnpj15yFFw$}T@Y{RfiE7Y;)j z-S~F=SonFci{3^9ZXHL?-b}&;-k$kdm3bq>z+*#MK*-4kUCQN2J5+M|CkV2ln}J2S zJ1+WCJ3V;Rf!Mv%>a=`FL^8zcGog0;d4Ayqt;QF?FK@ zy^-r#JUvDj)={x6h=gmtk@C+(4ptc-!N<%gFoAAum_Pt3vUhcpm33k`w$R6Lf7qDE zo_KB}E=dE>EDNVDBl@aeZ3yLljq$Zl)YvXpnQAGT9!U$~H*OEzP_!KQ;+W^zwc9dO zY;y}ef?q@WpliPIVSRtR;n>|!CAcjL5GLG}&Xy13ZnB1_nsi(t^wjn~OJhkHUkY-& zGgfBvQg|W}%SP`U=6PQm`)a6$;5#M&F76r6si)nRkYW7p+YTicSbk6=U1c-)QBz*y zc5YKu!qOz8nP6dJHqzv-m+0Qj3V~3k6mH<`ZkYzKS(JJU)SedS>q>_ZFudJ}qQnGF z!L_9-uAzc%{wkZjUe2cOdN4*$gV(t&2sZO@WNn(+@7yIS?h?3X;6-$iBr5s}(pgIA zb)&~x<@~%!I<4<6@CRPntR6PcJJNFZx)S9|*yAGwA@Agz4PTVy7(W`A<)s}S`;js= zxA$YxaBH!f^cH)Ppm-&yaOnrLQ6~Sdtk^8w+Wwtst2^!~V&C)9L2FO3VnBI$UU_HV zvQrZH6A;>dRsM)jZ^664>R)%xXxsgo;CNp?P*+xoyCUQFd=&nCGiSBdGPi5X^=A@H zq%j%oQ>0$`f$+4DZkKc;X7$|mPvEfn)1*lkXfM%Q@;fY!i<9Uhm~lqc#vDTt=BDN6 zJVBwnK`#3QL@X-Y0I_gs#M}$HX0OM%W9>ikO>;2W%FNMH2j6N@6ZOT9~M3)96!hk$hkjh4lHFR(%np39SbbhXw6?scl;>$P7v<#&Op1qnqS*PZ^X2{ zak7$fZ9>e(sAkw*`dUY*%LgVuk*_y;J!+Jj%ya6Gg{t)`+7#o4Odl;!vq`SakWxDM zh4CQ*Z6J!poUWQe!E~LySOjNzbIns(#`6ptlH^<2KWWE)LN3|JtoyAnAWDTQS*0XiG7k zPuh!`y9UKA4j$scl|YeZkABr^&GHr_q8)ucsD_)$pd1L3jm(W{>vQ>6 z0o7CDmrvTSIebMIZYAMr#10)h+qcHuK;of7?r}N449xzGq9-Lrjr3)0=pwzH`lZUW zrSG_XlWknFp{1CSHfECw6Q+ykz3lJUTQT?fl=DWGWJHP}dozXtRp(#Z=FXTS8HP2i z*CJ=Qc=&8+DpO7=_x0$_VXMVqeT|Cp){iX#((t@N7>f^$?K0A5eQ^EOdRIvN`dbLK zPdRuEUZ4GJO3G5K-xEp8?W3@qIs`Tc{zAZd8uvJG3{yZgW@v->q-3W4p71PL$p)){ zsKFI)$%9THTeB)le7{(ZtVYq?~7B$M01vgMBqFVbWY|Wq+WA)SD*3 z3i!h#g5Fc#=C59w>tk6itj>H{S_v^KPQky~sLfWKxh5FeLJX4D*6*QzN%v$#TdG9B_CfjF zdRJFGj~nq^G6I}iJ8;PLLtcP;@ZRVFD3m{C;EQpo=Mtza2R=3zXOBI6Mqxka=4HQ8 zrJrK_E|fXdALVS^dM@XY60E5|LWO^MGkCKT>66-MSMRx}N0##cn0wE#Cbw?ymt|cF z>RO^AB47mtAxevM6bpiYiu4kZE++KeY@mREf`AaZK%`42lw={&2`xw@p-4*%RR}E! zkTY*xKKohw-FsjAJ?G2GCoUC}%zKtG$N2w$V8 zyO~cr#k_f`N}Dm6{E^B1c5_SzFh+38665}*q~S;*OcdY@j&*TriQ@dui2!Gx~BmjIzXi0I4$WE07{+QMhlR2c9HTL`Q3`f=bUYkJz`G{^?HR}MGlOSi z{o%)b-FWxVh>Uub$4li7%U$^E9p?|T6(xRO{TSpAxAe8jDzY0{ZQtTHo(o5k6NW^9 z+*6!RF7`i9e)eSZtr>`5jj4!{s5W!X`bp^kxB%;^d9s_?chQ$+e|>G7Y$wPqHGexa z;+#33ty76%dpf+@v>Y3-$Tu-8eE9J~b3C;nPEuC;s{O^~5SwSPB-JZb^(2AX<2Zrl z&+JVpmz>$bDMHlnr!xVK6z+I~oQEirrO)es;smTBuJ6G#7)f`bYQEdmuWsF9FAxXV}w_hIcx7RF6qmx z3(;HESi9Zp;e@$q+s{EI+{!GGgtquLEF#-Cl$5*+=Bw=mKHZoWqyD){742YBJbos*2u;Uz;I~kEZzG)^^urcx-TQ5O8&U+haHq*}OSp2j_Ra`pj*{M)9Bs?98#?Hy zUY~N^T}9w@NiPJ$yv@RJOk4G!7PRUF!I~=`F+j{|iPl8l6tAfeyl5}>S8v6`3nSNa zw{=MDHd1^zUrES=R@fsASAUyOPin>TU%$zJUTsiK6wV}DU#-$T#y%VOar@=#!5ik8 z0_n~am)yCUU3z$9xM*>=D4lFrAjU!VUKv)IzRB$Hdgq9jW%OWaYqa8&?p>L>H@BBI zB^K&7Zx6HcEABNUf7Tq)4mj_5QJtxL#k6u|57tok)WE_4F{QlA&s1Nj=<`YZ*mU{N z#5p%LAX%ryhmgf6*s#B#cqeT5h@*bsgX`7rIxm_JtFX`clr6OOvY#nXbEsDizM1$n z`}IpBpO0c>;oBQlXl@80VwWk-A5$h6fcbmMH}fq#SG|kt?u>}_G&}lIMSlKh?q3e9 zZTNTv6J2)Dp^VGt-~O7^^aI+p_VrV3b?lp?RsqvFYa%x7Z*7q>N}{H^nU1Ra9|SvD zm^XPoa8cZn0e3AzL;d^o zauQ<(R>wRyiSS5;Ah=$NaqXw|B0{(rO#Bo$(m(Fn%)7W#eyqlrSYfpsGS@p^iZc*` zA)_zFo;|?2c9-I7P*dPDZZncJuQ(BuC}~3eGaJv_N~Y#qMD8=B*zC2g)DqS}tNq@T zf>JfM5BKsbR_JG4IC?fIeSOmVeoyPP=<69_2CBh zzam}tsbvkt-TfF(ihj-sc(V7CvuF6b(=Nqrgd6H~**%W-NO=*fqFf{+EU%iFmn1KK ze*Q;LMRtF&qF_tQQ}a~mt12F_TIp`LGE7}^8Ve5!=tZCxLk)h-@3O}IFs+p}?)=&8 zszg>CaXmwLmUekyL}FkTIqI3ea6kOb-p9f0g=|DV^W`+sy-MYiUDUy#Y4y9C52W4N zmKxr0XN`nE|2=5HYMoeDy$@W%UYuGRy1bV`h?AhUmWD?bO)z7^SYoBQ50qmCUJgYr zUUMAw9)L?X7G(dC;bA^&LUp)+4BupCwP$wiQ`M|Y7{TBr(q>5^yldOC2w)TktbUB* zJ>&?^XV-xTz9j>rFAt=?zR11j z3m|WQ)iSg9J<}x>=>}D=f((Q9&isM1HC?Il%S!3ZPXlNC56->}l2&f)}OY#*Gm|3zTEgt1IrC`m5wdLa*)NmmA3e@AzS}zu!qdV0GPp zB_=3JV*RuG3+(dO`kU}DPw8{%eP=BOkF@6-xJ-k@u}It5;n~Iq@0LH^70e5Lp;oT` zOm$$!xqtVcLN(*pi%x-JM6b>T{rA+%xwKc#BBmt_Sz7$p+Ll!Eh1s?`ze!2~Wn%WT z<3wj_P+U65&(3%1+-k1sX_KJo!g}jb;D-HNRBnbtIdH6r=yh91$E&hpeHP|k64j;V z8Q2r~t`x0;^bZW)ouO?PP~(v&D|-P1H4776M&mXK^Q(nI@}jKHKgs@YP;PUP$yB`@ zjX(8n<=_$SDOr9ii8g?b7ZBxcUfktZ;oaM%4K~whiNbyLbe4YkA8bVHZv0T~JyfZ? z)0*ExcE3A21-LGb^|)TO2~Di(88Nn+ZX1?sTy9vIr8a%g&(fsIF01{pg9Lt|&VPfw zu_q_%mliC$7u{CQHY}T!Gu`*x`*I%IDPXj0SI-SxMN!_&UR~q@3TD9YVpWc)T)F6` z*&OVt6xxG3nIhk2R5j8QSw2) zulIV!2+9_$P#Y3z+@AA$=2{SV>Z0{}hYAp09EXtj;1<}*!uoXTCbLAZCRac69?oBC zcvbOyAM>MlYh=9lqFw$%$^3WAfe%4=`Bl$c1Hu8ZE=F=ZZGO<9Ns;|AZKQxRU388R zZ$nyE?(>)|Y1^dZXWEkXE@Y;n{hOBiP0fU#5O-^PTz%n8W(M4N*7oem$j)tHo_?wi zS2610VF$H&U3AEw2DanqQ_X^#Q2J&+fio@7XH@J}gFW7h9!a90rOIU?j<@g0J<&H&z$d; znkK~kwr2`0y0yIY+Q#jHDt8B;{7~48&AM)6uxpdc^g{4$cpDN%`y;b{0#56;q#&HTmYR&|gSVr)#g2ylvjO#Mz??t&+sD!BD5Hh*sG zp)8ssl4izMA~H%>ZlqC&wb^*l>i+kV4QO~Nweyu}?~nx24Z+>gwUE3|Cg>X$y50I7 zO{FWQlr!}r@H3g)yEzM4$rf(19ieeE-Y#g>p{8*2x4F&3_eZMaE|ra}_R#t6zQ2d# zUOD99X+APL9hSV;*Bm?GWtK9lxMSIW^)t1D{#9;cut}6;>f{peJF3`8*;hE9IW32% zc8qzD*zC?J(_?ar>&xt0)+Q&dxmln1CSc;`HTPx=XJwZLn_D8B9a0tCyC|sYE3DGI zTDKv>2O_(SNq|RgUwqs1f0}Ue>{HELDu@qYy!o>RKuO~{5@l>!)_yfZwKGL2E0p>A z=*tRK_E#7_vr_wLm|M`vVD+G{dzUu2`UH}0Z6T$@FLIWL`o3xF9IKP}w_UjJllGdk z)AvIae@)<1_cF4TXK%$bkdTba8u+b}68?PHdXSj*7)$?si8}SUH_sC(E%cD{G5Giw zrOu_@qF;QML+&~$JoO04K^~gcLyLVW>3K$K&2x92bCRJ%$|m{7tUZ~}mNH`OV#$n4 zhsU=(jX09XNuGXbt5{DB^}=dwAx(SwwQ1ubchchX#|WvT_Il@^25#s>!J77s2>;0sK8msAr-8GViWja0;u8lP7LyqIWXfmYq($@grG*8gFDOvLf{JCc;5L zU$yetCD|jeTScNQM?@4>G~aWxl;gFT;@a!@>5maP{7A}jgcF=jlT$fJqI5sW^0;Uw ze3`gA8iP)`FJ}9Md2dL8ztl5%8R6XNd|flfe&u$ssqQ%n(e`@^l6<#K7+oH_Goqn} z)}E%h@XlqU}qiwj+q_jRC&^)$SAe zZ$4=%8rKHQbxHXyKVVc>$oZt{*3c>9zA?F@Alf|WAo|3Yw~WHK&-dv&)uVPu${hDN zj9zr%c}B3!NrQYDUFx?A8OflfA^YLg_9y4y24ce?eWiWmTeYlNqT~@B?U>Q_xYqc7 z?G06&!vK<6fuxW2dG|R#sEu4|ETZzmY_2O*rCZiC^XU-qWK>Cr-t!}ds~u>&F){tq z&|+?FLvGg6G4k2pZ>B!z^ZtxUnEmiTPqb(aS2IrY*>(1Ols@WWkgrQhclI-(?~{4k zacd+;k5l*!CT0n(Xb5FtQ?^txFt~!;;NlJcX3ez0H*+Yu9usUXG?sh$fa-KrKsQ|Z zgPQ!nlI64ZJOkP7e<4sB51Z$7z08KTclGP7x1p%lCH5@Z-T(`CdG*a^ zp{s@A5;={A1q>Fk{-tnus!QGSUefb!8C3_PGUF+bXnxyvlHgcf$JwknbN}iM9Sq$+ z9u^@hSRt%rzXI}NcpXyJc93$6dxkT9l61UZw8k}eck|Jc06-doO~Ceez1uRe9jlC> z#WJ)knwh-V2)S~1L_9D9*^j|We|XpV{7TjehXZBZL;Ts{QePD4pd>yBCps_^5%zTj~lL&8{N z*45zMy;V0Ia=d4XT^~N)QZoHjHJko+0ayDz`R*31wnZoD!0^P;B-P)J&5!wVga71| zQ0(dNFCi)D->*{w|MBy&tbdp-{|9aAuiyTE10eao=X(5?$daFec0(XK%CZiP23kKs zw~h-yxycW?7iCW?oZ~y%zP;JCzSzw9|L#XK3lkI&1pM%@;FH92Vo(3lJF=jt^v7$$ zCV)MBW*YwR!)80yJ_H)sAFm(0mcM^i(`=8ktuiPyiOq_TLQ?YGbM7oQgJR8_Zy)~S zBTWWRKIngcyfN(Hc&)(JIPS>FCsx?6Mv@o*=O6F*$k&*ORf5SQ5qlbY+Lh~A<#_GS zPw{Bx6{Rifzx_=AjurXe)qMZI{lqwseUEsYKpykM_kLKtV*rgYhDr<$v!)y2Pek6Sy}a*;UDR5@Hg# zSKfF`_Zz#}c~BGV+9u;GV|aBhUV?DX1I1R)I})S~hdE!jG6AgxNU3@w>kDyHV)ElJ zr893P^p?1hB$*4(g(vG)N8$lM+sMrZ=p2E)KEAX|LF)+I;ase^VVo;2U~rX$C~>FX zNjPtr(UGi3N|aWL$omt9KLr8BIigc!XMpX#0q|&9w;Mu4QdVXuqWJX^HQd@FH{$IE z$x~FjG8>b0LOa0WOQws}SwQSf5OP|(Yz`kE71*3(`SD zGPUe$opz{r?g=@BU-I6bi5~lphqY>}l;@ioW?d$1vL&5yOQd4GI=Wp&?5Mkr}7pj1?CAz!)5^AFU~H)IoGr<=cCM+@U|$4AHk-cph6S9j96U!`S%*AV$H3a^bLPA_8lFlNn3$}IV9x2^#WC)l1G&P_}>G5VyvvB(-VA3e5HUnR$ zLvNb3G@tA>WFzr<^!4=}fVP<`3CWvAVL0m)jiTG{LO{<6T}a&$xK0-xQHnBgV>g!8 z8D5Ww9#HLwOAXpI27`M)<-DX`by-qCr#uiLI(87hbnO*72e?$mTGl`_u7#z|)l6o^ zUvDX>9DJDV6EIYj@8L)%&CBV1UvI^vw!uekzJ}b-O3ab9iI^<)=Dkw){u%-dieZ1Z zvUQ+02kxk%l6&=AeA-v>VQ_y73*qq__$xCb(z+a7os~v9(1*8ux)GC~6Nn-nzkNCD zDcaeS-fLWlpHq-`{`$xV{k3M^HgSuqgoY{r$q-C;`YP3~u%;mis<9SURd?GFIrkTR zMTn8Rw*r?&ub23BrJQpr-Zt)uy*Eg8gb^?KxcGxy2CB1W!C3%?iVLUxd@i+v2EuBo z;J76DntRpNp7*cvXAgOm_%0tAsPn6YfJ=+O0oM+Qp3%U3-O@nbNE%BI^)2k{6Kz)9N8F{^XCP3drd=?gSsMFzbvRsao^Vef~&KL?YeG?A=B#gRF z+JvWHuI>nK5s1ibfNT^uS&=wPkLj~&js$8nzo8CdAyQGA=NdO12$Cd#^6^5jbLcJL z-D1d;`+9!=qcp182_jWHEDm)f9OwS#w_L3g!ox2%;?IZ}z$cwaSz`Edat#XZi)og9 z2x7gY_us{P_a09e3}K7`983cct!b+;C-n4wM@H@(xdrIJQ_J*o``8?V|&|K(+pt@p=WqHog+ zE;a11U7M_0us!^(A!lGcuFthVYI~Tj`fSysqmXLxB zk#!7_JXO2NnubV9QuimsA>xo@Ze^ze;~cS;w9aJMfYt;+1#$8=opuel76|8&EcXGx z-H=ALOMtszQnPSSEkBv5(mf*_cwXHPXCJJfyRA3y)SE+{%^&}ZuOOO?fc7KnA|-v} z4DJ2jFo2;TH5L0>YNb?n66ZG`3&;=cSNY6O&Epsq37#Z#FU|TV+Y7R!`U*@9cc`qt zf*h_8MncNF`INZB6F-QyiFX7*Wm;fi#b?E86GUvH%E z(*!t&Px@hZ8jhblh=N5w-MKF@T?KperJRc!J!tbJ#IbeQEoMS~({s?!{Z0MT)YvFh zR<~J9nfwR8d2F-0*-;IIgZ^mZ7OicSB<)#eW3<~5*{Or2gP2tRb6qNoGRWovs7a^A zHtuKPMQ19-0eN(AJuXZXB=+)bSvR|>kA{8N68x)^d?FU*MFPkj8t9zer~BQV1$5Zn zdzW`SG3P(*Xg8AH$-6SI0I0o5bL%?6EJ^2ThN5UCQ^6QW8{Y@)gZ>n&JTC@kl7CDI zOw!Ns#49mvTN}0t%fanTzVu}@ZqH6$Q=G3d2TdaEvK=lxuZWuMgJ?aTr78z8!52-A zWe|1^dQMC9vO@&&v6ls;tUvg(T1BZ;BknR(ZE?{XSZX=%O)ibod#2djU0YJGRa||r zSM>X?<+j)jP7wk>%(Jxs0me4>4z`4UN0^7-Ycp?4acQ$+*DQVohvQ$7mBV7s_X zjb}sR5o2(ePh{~uM`zcR4aARuw1;D~9H+0uhFdS^kCwnvn}NkiNMWCS?~d@^Zp{}Q z<>fa?Zk+>EKNz+S)t{qBIdH;}!}mGYK(_s$gh}7sEy`E?GM}nUq$l5WswOB=|oB(Hd3AOX9h~Qv|9y{PR zu$6}J?lT^5|0iAP^-UDRLyA~`mLIP=EUH;zh-^vi+s6 z0$R`sAn0#e51PZ$T0nmY%j`PFT#aoaL!T9PP^?9;auvSalze-78NL+f8DAMc9KcGH z>s+P}Yb+rTA;pcIBFokC)Y&W9=QW)AxsDwK_yFBPx=RFqs;pxiKe>#4NMHWSs2GJ z*S_(Q+-M0BNMjy&lh1X&i{gm}Qvt1_BNQ+LD$eETvia^FvzQeB#j{MCOZ}LdWlJvo zB9u9EJ}CA4_86A)BZJE_4!uS~EIcPBg|u>>;axxLp*KDU(4TUIXonaTaAb=LDp(u` zCd0G9ooLDWttU`irbEXf8=+)^pgKJf|Dfk(szgr{9Et!I%sCueh)yo3DMNZ;%>uOd z`Ap?-64u}85&)i}HIdSVRH)iR128X9pmmmI;=qo4r@k^^W9VH2F!8>^1+d=Yj=O{H zMN!wDHrW{^0j-OJQ#F6lJLlg})^2(#Tx?uqOZVY+>UafW22;FZ(f+e?7K4)UdYv$6 z$0sV#B|Kt^H3JG?k%mY=ybOeGeRyyTJ3&cHr@Yo} zU&=W9rf+w|b77$~fPzp$T_iFB0lPp>FbvRs?EraD(s77fYg~dFQUH9Lp~Z%Ms&92- z%cX7VMCcwaephFFatDNJ?a_3;K?^vn zZt0HRhxN~fi1x4b>L9}SEJA>+qL8$iQ~-A-S2#F^05t^6f))1&M}NokX?p2YkdpvB z(k#WXg36KCSHtn&M!DLYYjJ#w2JmM6j7Sx%|Li~Z<# zgawRxfZt{DMX*YSUlI7X^Uf)~eux^E9-ya1GucFy!u$WWnTh_~%qDnzN=iNjE)oWk z)LCV!8^k2t=d!>;#?u_NZ@74z58)3`@*ZqKuf*Ml16*~uOThsKOOUoJ91Q5H1KAj- zK?Tp5dxSk)IhQCIB+seOz*Ok8yCJ#kj;XmXJt!04pt9vfkYQKFcb7TD@lLZSAyIwD zeIIXO5@P7gMLS%QL;BkoLkjoZG&N8}DMdR~w;nhe>AS4&hI|n>bn_)H$Mx%9zex-2 ziP&21-nt+1KxrQ@IHZXJHs)d9X=H+eM=ldraDBrW>|QAWarlJnE){Nz$JSm)g}$s_ z%IJk1LgqgK9YQc!e0z6l-i2Beec=JIqkV{6CH)WGi{kpZhZlGGCtLKa29%vh7L6t# z{cW!+Skvaa?7M1SKWhWKQsb{U@d zS|{(vPWI|pbHLchFt>C0m;?T#c8tta1pFErQ?PXdv=&-i5KVpiu>kV(N8<47V{Sgc zHsv}R%$JR~Ow&ax4g~kD@ZzGBH=mge-c49&f+SNz$`DL8b&JGGGv$W|RL(9~H9Y{~jAO_%c z-VoxKY3bm*Awvtbb`wZ#)p_o`e}PS$^)bXk8$B4(fq+2ha{S6|qP1;5yH$?Hdv8U? z@BOSMWd<#S6jwf635WVd!PSwj+qmx32N#&MKB}3Mq8ZIrs&S`X?%C4IQDJ7%WlXwC zO}fjy!Q}A%dW`t#CAs*dn*h_3vIyD_$Tq0iw6iGvq(I&+*a3_4)%l)t8)M}6 zLgAZvjfd>0@A7BT#JecfIOrZx`#FuE*!LKg?)(qM*4TPU~LDw-5Tw9(;b@H~3$*IJE`}N|~Du%)+q(EoOSVY&10v;NH z7I^>|8~9ois#oqvl50>C?aQ%>Xryk-`=FLuyX{eJzBXFU)sM4DoqcrsorP>Nz3Cme z@7rEnrD1LDO-uSl{+tKg$qNl?7&+xeo_J8<4e8lkUZ*i5nh_py=2XPz`F`G>2wjx{ zo_FPdz#yG(DLa1fn|EHqu^LVxw0sH?`1%899D}3d2eT0}fb41`*07Z0A#rn0Gg1K< zeFu4V?mc=6a9?6oD^S|7M~3=&2EgFvhTe;6NU#W{d2_e41}dJpYm-W%?JD{&o_5BV z^y|N$Hh1i46$Z5n-cW&DPp;fiy}sz#Z?sg#HJb>|t8vv0nP#5fj=`qB6u*Pw%j|>( z8p8WhQ{X0cIYJTQ&C<{N07xQqf|=-T*b)}KxC#kt_A!z=d(XqzO%U#ewY|1nX zccT7GbO^huMCXfW&yO4`m!8!~UaryJStBfKhj7#}G)_+2=?Z;w2RZ$?CKZ^H_EB+#^zxUeol23MHpKefZz>zWQ{iY~6 z!T1NfVo>U+X0BGf^Wr#@eCEBIG|%x zG)HBj3cy@|52h8Q;wCzzyWS|G@Ix{I@7P9w^@d$&!a-T9gv(P4yz7ETo7=$xj3-Wy z*%X+fnGgE&9SW08xbmEw%zSLTi2lasQ6R1`vHV;TjJH}1jS&HYSrqY7{O#2ducAJH zxpWUJaLHiK0jJO#D&eVD-z>DByP23I@~_}VcR-k?ffTB?pyzCF<4r?iwvM#AsS?=9 z!$c9H(t^<&&_+%|;yeXl3rRam$A3OA8U$^j&MypF{(!b%IXmqBh4?EH6$1 z#+^ui5oy5_jdo>tRgh1EgM8XzIfY?-qVwtK&rtfKmOJ(h=^y>UIt3Lw)^I?|(RD0X z2UYgqbFWg4EMPk`6lzF?Sn|lsBZkNsvI9$Ia1g7i&RgsbR~$DLhrjkB9MprMI$@F(E2mu}Z% zq*vY8soiB2jb&ZaRNtlA#n^~DEW&;0-0%FUC}O?##qvjrfS%FHX$(6g z>!eI~I;M>Wl%-a-u>Y|l`~`9c?Evz~`@a~^0A4WkRNUlXlO4F(=8dEle+oyz`WYxC zCV7_GG3$!z`f)}2`CJ$K07~>x$Hn=d#HwS86BVvG`AAR-{QH&p$N$RF_V3k=|DV+= zz-gTzrMQ- zNfq!NMYKgfgsM&er+yd8KGFxK6&%HW{kDdjm{tj3Taa3T+jSB!e_lgdh2GD)3*@}| z_x8jlDS7A40{6C=mpP0d*ejV!F;O<_Rj|n+ui-dL_2(L0DI`tM*fd}Msbad0AeMvk zBS@{3cn!Nee*FKsL@*&PK8G6FM zo*;mpVl)@aGsc1cH`6g*(zX_KBE18yI(j|8AR0gigszuI7fNKk4D3<^;&=q)?t+f5 zTS{Nn%|P_8E@t-5=@$Wg;wLA`Ldux{Vd4rkZ3RiXEYM^XO5(WwBh~V&IV_jFc1rF! zEInHw%X?u=DrnOm+z8p3j+Jx0bBimk$Sw;gZw+NI+5tWVMM(Y(;_B!GX?#3|wH(t< z@p_e4h`Y99pU?>asK0RVIE3?}c6l2& zm0$uf2NPmb}iyDsjtE2(FP$wKr+~M zDhH$ad}VeLif|5|0iZgkmbP%vtg!t^`^>kVcYyFoX0o+ld*f9Ce6_}#MA0D9(pysl z?6n;GU(fuQZmV0?8em(#Qk*|>48Y}M0iw&2b&Rb{|gSv=Fj#C`OIqYSS zh3){jmg8=&W3T^tkYyUgl>wZhJ7B5;s-UIzZ(OJL)69Q`mp_e1-2lWlkY*CF*$COw-!}vQSGD_Q z+5f)8ZTnm{$(il)Z?)!Zt7NDnG7Nw26%4n2IZkpJBmb!Oq+(|cNI>JlYuBRz9lB**_}t5dB-#+b3Z<4k9JnlrTf3iQo)>pO z+~6h@avA@#9*v#2eqdHsitMf{0xO(fuz=#U6i+N9->~!JCmFw>>!nZW&G5N3=lakF2D5BQmX>q!lk23;5D)gIKo$ z`O+|1l~~I7nc;C*oc|#LmPoZ>VMDvTdtv?S`*l;aZCTh@K~k*!qRIO;<oT%H*I1 z)k9iw5rZCw4U8_GK-9=@x;8AINucS*b}Y3=y01=oM^RT%C%Q-$sR*uP{H_lI)Xvh6U5mt1SsHKf54Y@)C|#R&%MR&`4=SCz|8D%t>^&Fyza60-$iJp<|^gX z*t2@qQUv5~irqcqq}}=*#09RjWUp4q5pBy12p@C@7jGz=MZ-bd;kmmlAE+p z8|Vr?*@{V#qC{SmA+;FwDko&@^1EnZ1`X#FIAJG1=L%EMEQK~V1hOextpVZ#2>rZQ zVMmKdvny2*?&l&l*4_AJr}U@sJg70^tjmG<1)vBIKOkBGZu#xV4VE#dv02++tddR> z!B-JVTXj?`Pc&wcNCyvUTX0td0pkudYAevF*<~(qd#;~WOnUwC@Y%nIP6IoXg5J>b zWSv$Vs#6$#w^1iBzZq;*r1)j!zB1~!W5(~#?E+vvJp4NTIQVq&h(P95xrc+tAd&)} zvq@3%=!UwV_|$ktgVr?sfXeSP_Nf(V1allRVJ+7X%-*Upm-Lua^w~vluYW5lb|lrm z#QocsOFMX~D2W1U7O!U*b05;xGXZ*ox?}Dg;Is|-tvvJBY@cP${2zt)j@Y|559H@Exjk3s}}!sz9}FVlWFdAuYm7rUtSS z%I~^o+`vE&Xbg+u2asAL4-&ZTkA z!l|gJcixfsE9)wL06W;)inDpXFX*<2PNKE8M;Fpx3{J-kPViOw$YHV&XIgQEXW%YV za`;a%U4K8vpR@m^D56Fgn*AE58S4o%OIn`Qejc^g*?#cXG)EW+`d^*H7L+_w(JHxA zG+h|a7qTzj3D4GnP$xBB^Kn6&%ML3&@?y`5;MbCZ{#z#4k^O162Yw(L(RTjiBaD`VDhy5;gg}SzPanl z!3xpE6Y(JX1h0f>pA>Sn2m0)`ZscCUl_czIkP1t2cyIz9Myr}7RuJ+=y3iu^3=k1VWJ@<$nFEZV(a(pvFR5zRs<)#3`PCgt#_*h=5zhGHackMek| zV`JYthky!16n@ZEIqVbwoXvsn4clJ?zWWAaY89m;kJ!rfq}>hFBz*ckNXyZntoBM* zm1)!z#lABfKtnRxK%W%SHUHh(2<^K6@-~wor?I?D_8JbX#=C&Wq(r-Q%2WLJaSa@gV;E1iZHnUhix6Pe z_ZO{>xEth{4e%sS_2nQ7eoY7w%Wh58?-V}ov}M~n_^!$!-@Ky=?ivMjn-jAjy~4!|r1pXsAX4g)2@XV-U?Ij7^*HbEBje1qCbObGdn zdK%!bzTLTd>8yHPAiZL#{s{$Dchz^q`KfHY7pTpQV}~F7mRRw*fFSy9lkQ4xrQJdd z6F2r9=<<+GS>Hb;GJI$%wApA?7pv_BZ@#V6jJ(Ka@uiK&FyG7}?luc(U4FOcGCAiDCx&`b;<(cm$A}S;Jgss!3fv9;&X^= z!V}z5CjiS)2Kb~+sLHFuqM%3=4@npt{Z^!qhPc&XHeJ_goAlSh8f$9D{3NiOO)Rbm zPUPkly#_$#w~0Y@&hB%4t%=f4J#T_-?l6`;=hv}9uBb69#AQDR;SdKBbW-WhJCjQ# z`80w2aRQXk-!6dsc!K5mJz${>Z98y*?^0dyR5z{;d!swtG5t zuJu`hel{8aFM89jRUuXH>d30s;PA+S?~d2INh949Gq{H-q#E;?l7D;4LEz#LGnp_8 zCdG7t4hQsdn+zEa=-8wO>Lf134mb^Qfbf)$)#x_l9)l=z-~q}I%Nvj~QoRAK4+Xt^1=1VV-rjU=!!&`u8^Pv%$_^w%HV^y6iDEC$|BdCptZuh+5|9 z{_*1jblQrNuudlXx%a%`eXLFm0fvfq12w+v8VUm=Va$|%Yagj<>KQ^jB>5wpXkR|_ z_DYIsOmg7psT2RcXY5CDq5}eNTg2P_re^U9Bc`QOW`PKx4%9D#?KOcrWAjCK%=#E; zW!*U6ght6RwlOFfR~MJ0yIO!miol!B8ow6gP7!>c>}ldA?cSTRKH|$3G%oWl9!T;0 zlC7#!CSCL+trFT-8?Fa+c7UHE@1^b(ep#GtYlQR1^6)EkJT!F5Rq&#V0rh4yNM|Gp z?}9qFloGFw({UZxa#+y zeJbED0ziP@!C6`Qi$sQ06K-2G;D4CxDx~=&djVu7)Va`S$aiZR5?ukrIkT%()Ca_3 zDke41Ry#tsim?vWKtv-+fIRNCr^+;NZFDE`2F7!Dj-b(l=Gc8o-_vBhc5I*?&5PL8 ze+Ov}?cJO1(^cQt3B`g=Dt3)dZW=Bw&Z zO>T9`%Iuv!o56h6pmmfj$6d92oB$RPdc%n#=T==)hpHyP!uenq8rmgmI(W8vOp`zJ z%&rTc`88t{2aAO&bv&i{Snf4)u=L<^lkWBJ4O?wq&#$6m{tk^g+ehqJeL1-FG+Hdb zG_E|`mil7?iNyg^3I3C>(kaD_!4z6Us5|HD$~v8@Fe`_zGVcUs81x)C=fLKZd|!U^ z;lQ7rYNMczFy7Uv3ewGDacdnCKenKYp&F}KW>QT@S6~A)zJp!!j$AEyAnVc!ZjK$_ zbH$6^06Z_CAo^dVssk;C4}*rb1fqUW^9>K+J9==|l`N83!IzW5Fn_yrJunUQbpSyj z=;g)Ljm`z>DlKY9g18r3a*kznBS_7C=1YAdMK{&rmKK1L&{Bei%^ohFr~)!lpXq{1 z8*o-o*%h}dp6=qZaCTFH^dEt4k?rxSjLDl$aY>yO3MK0^rC+yy@q8Zj7}rQc+7ipac?5{80v3ng`WYuKY3t6&p zM~f}s$k%afSF`UMhvBFsemRJdR|X20;E91AP%;f#u#Kqs?D8mwYuC_9-COjLTSh-s zZ$7^?BUiq)u{sDv90C`;Gvsl({YXjKx87q!f=edQJWtM-${Ac5?8_ncayI~<3f`Mx zcP70Tb}JuR>z7VTZ;Z)z?c^nFs9zlIOhpwEe_Z~?ovF| zM{WR73L)?HPf^OQ`{}Cte}HlW$qtx=bOO#{b0S6;2;btz*ZIan_G}1#{7ua>3@lew z`PDDux^HcH%Ln$`=$Y7PC0^)^(9YeYtP2{-kL z3p#Lts(Vn2)rdyiR~Cv+4n%b^>aX~5(p;#G8(|WI9%QH{m;|X3hQ{kqBH{p{`vWNy=oY^{rp0~Ll`|M-`*XKO2y-2SLFqzXk(;kL${R0zWX)1L zyM-G;tDRgQePHYTR{}VuPDSG2&G({OWrUkVd8^dn-l~Px?Afk+x<2*-uSdwG>(5q$RI!Q0+^+}-lJ$VhK6d_~FWxgOd&^ePEuuKfjch>&G|8;_cV z8qfZCQmilz1VhG=m`O9!=@oRLn^kBpI23=?4Tq3b{i@Bq@42}Ry@cbxMKFR={d?Un z=Pnd(-$H)&4M0m1vYq=P1?wrtqC7ajV2K{rz$&Aj_I#jgbAaE(dUwLouA#Z18siaL zXWpN;CZA>Y4CKQA3Ht;QnKB2=t-`VEH1FtQWU45 zlI2{j<0BA-=(9!wpVOaSfnD>Q^$$P92bG8t7rdA00Z)B`4G`M@mPOZN5rxTtwx|B3 z$Kig3Q#g_vQ)jdd*Hq)ve#nuB%QgNl#z40AX2mm*C$SBAoU6}JEw1UQHZGxSKM9;+ zxK%}ID+crl?3n%3ANaA2S-gEy_)Hw5Hh}jo)X?^&fq7n6At-+URdB#+GKXFcTsieT z$d#DjbTYMqJH2-7$8|`qZxcwzQa`x64K1C(cO)_E2E8~NRQm1NG;fF&J6!9NeNwL+ zv_X;PIq+|5<=WzB5&~_x!Kz1ZfPCPP&~;QixM&X86u@K~LM?~IZlj1@RJov#{bC@t zffWnwgK}InAB<638Hjj;yp;Ekg@z zeKd1u%D=)o2mh`^PsibY$YUMklvB7@YjhUS2jK&sVsCeEnY9jER^rqwXPQBs_!{i9 z_^RboGCWFB3-_E$qI|89zw>Y6BOf4zk{+H$zDJKJc&xMQ0yli6%O=aFZNZ}KaGvXO zBb>jL&!))@L1P(3(J1?R>ENE*7yr^i2WYW{jxJCR{PIzK6a3jz20_FO^_+b&f1M(?IX$w@ z#J^1^5Il$p@FxKeA9Jo}?DMvNo(k%fuR&vpp2S4spF@81dfTjvK&a=N+_DccCZkZ! zcEVF07MN;o>oHT9?CcnGVie%-oHJVg^N3quv4x-fHhDw_Jrs_D89nF<)aw6n#k*;H zacIJ^vKfKG3SAvrW&)KhCOTm*R3Y-COX-gZJq9MU&!xw}k)?b;0%KY}=QV(}dd@#m z=~cAuP#yr7AAOpNu}9#jTITJqva>N)6cxqI-hXh|tq!{h8DCTnB+4p&?wgv9dIr=M z(oRWVfVzWYr8+47x}FM9LgUvIcjcL`UID##m$PRr1CFF$+F-e|1uNTIMd3PlF8TOr z5N;1TZ+K)Q89;k)0OdPzyPQBdISX*NUB6VCZTd5B`eA%yK3BO|VW&G4J9r;#7Zuc=?0R(IVPM+QVYS30Ol8WF+g5XEvt>M#FGxA5A{$re;q_jE>Z7-n8R-wOQ!?(;X$O;L{p7{3q9o4K5t^)ZH%CIw1{||fb8P(L* z_lsiRihvsnqEak~NK+7yj+GJtrFT&2Rca(aP_d(Qf^-!EA{_z&0z_205C|nwBT_>M z5kiQRz?}=-@AK^UInTN8d&eE;!#Rf!jG=p*wX)`1|M@S!Lg^{Zu9QNmE&4)JW;Zd9 zf}61z&yXAd3D(qEDTqf%c2UFB60-{@+-(0?>*o&uOfX9onp3yISyQxW8`-WL{e7pcbtg z6VJHn5Xjq2gEA4QyD+*4JTMYi<2Tu=2?V|!hot+rUIAk~T_rzifBi$o5S$zzU+b?_ z`RrFO;(MDDqW#Dn5=Sgc?j>tx4m&QWqcV9xVU7ZHAtv~+e}x8`e?1LY2l`u7HcPjF zP6Wfhq%gS|q@0m>`zKwXItW@FM^SH-Kv5TOpN$(}bMB*HQ`%^2A}g!k7r{0y)(NOI zs)iqQ0Qj-t{EtgKiR-DYSN7^z5^P9IAAzW}riGreU(iBvqeGueXuqP1W!$Ch>dE6f z_a+CNYuL7@DTp^@m}_6#l2N@cQ0^0d0{pV}pN_+3*?0H?DEe^Xa2-1KfQG7!^XtmK z-6AN_wNJF%0Y>%v30!9&z<41TygJ|H0ZdN<61GlS_7uFdv^1GM9<3=P%k$@X%1crR zYxuV3*DWrhudH!?XGcfApX~R8gJhG1$PG#GrwsPJP^OgVtFvDOD|C@f%3?{-Qty)@ zI4ivnWM?sLAKwMouqqtjJ|4l2eE+-%D4q6W;)Sm^i->~dSv>!I@@Kecy32i?btKy! zkl%dPxA2%5e)0v`@586sU@oAPi5>UL5 zM2ZQf*BZ-Y5E$3;*$=jHK9F+K4{rcdl%tT-13!u6%GACG{yvG_6}|?n*ByXzq*>WloXtcZOaRh4Xg_NEEqf#k=6Lf69 z4I#!ZsR~gIE&COEext>PpMrDWde?zdr+|a-8U3c|CF6le5@YlSpRLT~59db%rXbls zQx=$G%_VTMjhI2^yM2-tpH;4u1DNlUOZ$<)n?J)HLsJ(XUoE`9oM~13_KL1=>>+H` z@ZaECd|IQyvxDhvd)*PEIV4>VS)hbVmQ`@*%yhv}W;ZgZMF5wZW22V3_FZ!wbgrH% zx%8MjehF{y8S`O+=`U+=q%B>+_W4iZG62OzdRbaTz47{3yFhH+K$TX?ggZeQE@&pV zc`M&;*d3eA%&}Ned4r$x>xXR6J~u^A1poOW8Oj0beOK#a37&K^Vc+wYNQQ1~S|`va z^!zTHw%{9UJ1EH07mf66XDqH=`4njF9kljhQi*mFe+t_Qko0qzxMYS?2?MmP!3@?f zxe!cn32k6}LdvjDhZ;xCK*DK-uZbJ}j_gx@cTqZVk`GJT!SQsz7wTd3fNRXZuBQ=d71@!2_|_)g@ieGm_vZHs|gB`PZbE)9*)K9+9Yw(HfKHFaLp2KI70R8C*&M@+5cjTCSq0qS$V+kr-leOc19%M%zzoiZP{YzDc@DMtEN9a1ZGyK3(QBl^R2?U$z+pG{w%+k; z(S?2So4HowH-{fsNht1P$6ZDwpLn$iJ|qG#Jkk(LF9AyzHnk3Uxm!@>GOz%@Jv=i7 zY)j;_ZR>aKABz}R$+i_Lz`wyN5?HfcrnO5GharClfMBgh{L6Rn0W}xeuI>TEf0haU z8D0YXz@gzUe=Xo|LtYk;k)X$bz0@n^xzBssek3~WXoZYUl1w|tG0l5Jbbb!8hGP$V zRrP_6ebe2rxA&O=m(O$MJ>LRJhyv&E6Z-0m7kL(C7Tf|#CxE;_Oiou8a5}2-tW~FB zCLEpJy2@X=w71l%IWsH~Y2*s;jNM@DyZUo9@_&58#7ytKp!J5V=HCvoTF_|oB!1oP z5iqc5Y8{9MjG$)Va|GEwmK`~NN8`OoPR#IFyga|$&DHZu^Wg+YVL`5I0jQ`<~!=AU%a%9n&|Eb;+M01lq%H9oNHX+L@j8K z+L;v0!;K0BCX_;!`^;qBNd@^YkfZ)f-`K1%yuON*!ths9;M@hfzn^34PoPNPur$9P zvWOyE0p&(CWhx)dDz;_KyQ%4Iy}!I-Cw{Tum3@;air)pOL`O)ZwK=z{1oG(45sG zJprEOmbVk3GG(u{RphT|RiX)ypPduejK1xym-pCprH`TbpIaF&oa?~TO*=HH;xA0# zc@7QY%A|952bp!X)KEXZ(s!ci2ss-R+vt1jq3B_N6-e=SM;}rD+_;to z5Yujnk+fVp^GV6y74UeJ%Gg~Bz>Vl}-M@tm4h2r8xjp9Khz2irl7b>sCdj#VM}eK( zqz|;+6>ACLwUh>!23Y|V75JkE^cMkRiQe*pE%$-AL*pS}nCf4j`;R5xfO*z^+~)X> zR<)z6z*<>$)qmuo?2BH&QptW8zF*uCx)=oH0=+-t?u9rt@1Ow>Y?A0*&V8rs z9)bMz_6YN1FkQ@oVW7qH{GlD z>^v4KYtVnL+Y2u#6B0V5nT>Vt{21({0E)@810ZMt$X;Lyo$e?xjcrt(b7BDy{8<{@MJY%reqgDWM^0 z4q^%qD-7B-0Ot8gGMEB1cyy+~jj65uz~Xw*2Mo3^wq@)Wfn1lz22ewfnjL@YkHiBm_LIy#*vN(i4@HP(o={xbItl{%Q z=grogUZ{5{epmZ19Uq!~cM0du~!hdY%cX zq(Jo}nAute%zVA63$4Mu?sx&_rn#mr0GhqhyoE&;1OezMOS;B`mTI?gjX8P ze9v_uEyGRmCv`P89X|b&Bj>>%r~c5nfzZ66Q71~weQ;{oT*K(Oj&U8Q&faul9QT2W z*Wb1j-(=x}oVNRX8jR8Q^lVMz09Wqbk1C{*Kgy#BN|Q1rN>z8-vSac0RX z>sspRt}NBtfn~0wl6@S>M ziwD9t4I3&2KnbXf(;{`AT8P&fJ&9GUY_9)aahT$LW^lA%mkqwke_AVSI}t+ooece_S1kcHUQEu_2)k=nKBm(s9T=eL z0KO|tB2gy)Tjz5@uDg)4@mf@Zq+!E$UZ#xm58>P+ojNH=a$Zr$kQJT6G*$OK25q?j z*L=>sjpQZ%#yR;KIq5>BV zW*I2)J2rTeBDErLER35d@boVAJX-d^rj;VxRn>mz+|w*xk>{=5V*1TAtU@Vng30y^ zvhuFqU#>b^nVni{KaqHDNt@HaIV$f;xN^!MV7RzDkh9y<&jpsm20b7Xvg^V`MfGF2 zX#)eb-hgCa)_3g6Ejk|GN^E}K^YO%DN5^!Un9DU@nZX_lG)>-6XDXcMGAiMEG z1vTA}gk40lq%P!Zb*isfoP7g-)ebb#fOnj8n6JEBzY$1ojziUhUlkn*F(VA8x3WUO zndJZvStD~ww*W1(u{cA$_*?Z-(G4#THFw+;oqgb!kgggOQ7z+!s)4xg5?-@|fikxz zuDJ|WL}O~HQhi0<87e=&X(VT7=>}Pt;zg_S@H?C)N?-ZlT6S2gc+4wB7?un z;^ZLhGZIzxCQ|J*fLm)b$^eBJ5dj-P+UDdK6~9$k`x!d+$)7qFttsg5166~{Hd=C*TEs#0y#didDNo3 zM@7HNkgS99(Hwg?Et;p)CfXAv^;H%79_+U`n$t+YP7vTIm7}E*IOJuY!Jgv%C$FX4 zU1hj@Yh(voMB4&Jm{W5TXiPVrE=rIHw7eQA2!Vr(b>=}1V=_Uo74FJbcWUjy%PG;b zAK>AIzrwxmM0*)K!Tj)4nB; zU`v|Cyn5xlV(a|+L}^hvy5Rbo2dJ!l3p@8$OJ}hvG9R=CsuD-Pz4@SYK+5RrhMTI! zqDIjP?ML(bC9I3=?xWvKD2KjlH9h6!q61>wd*ct82__HT(IW)Qj06ZPQc*ykY0@G| z&@u&CTvq7I(X`v5ZUw*2Cd|GQR9oG7*iwUW(V^E{p`WNUTPwFN>2z9=#h?gGbzaXv z_`?8_%+2Lpk6W*qMU|fzOm=`%y809@fL^Zg*yNU5__2^R&}&eHotR`XtbKL4U`}6N zxoin@GM#Y}EqHP+YG1*EV8YvRkkw-s27P@kH)w=Sf`6b+h?)Jk2xD?cVN%zFMPT)FnF^!30uqp2Jk zdCpk5*$iaZV;@thd@u9G@So{1UzBE-|7`Y#lceaL5|N>`QN3YEiZIJ{x?8N|PTlHg z&BzV+D?A$9^N5+wk%URq|_4%yD>E|L+QLfi9DQ0Z9!Vc!M_KQX*%X^id z6ThtvON|JB>-S@M;g4ayt{^Ley76j3${WdtJ$+8;9%8>jkg!?I=lozT3Qt9Hy2+mJ z0F2RYwCpT2slwqS$-)<44eZ@hk_yPhr6V-=VNf{NIx?la!vz>`3#azcG(uXt2*ChHA)5e&bx7?oh0nV7=ns&p1A=G3#iA3kVPyqTjImDo6RCn79b5H5{d zFo1TUFMS9{G60}FBLFU|Lg)11;OWLMs9%Np?nl&gRxz#R^S6ZM%6nL3SF9n`$v|Vy z!DY#3TtZixcHkP2l_C(Y^C=Gnp&zp)sut-yM>zfNE#q|a$+xX0OaU>pPNTwkrL&5!-T0dJub=3x!w$J!**>;Mpso+g26XYmR6XXp?N4M)=Vkt@9*pYcHlH z$%u$qdlG^cr)DLhQ^*9YYmY08UR`ROWL>pw1!xvZ)|42Cz%G?J|2f2vTrux2_Z)Dg zfRxSC#l)n<-cA4;eBj_KA?QIzsqT@`E^+QWhAW+~ax084u*PXYf^m2cT^yWxawAiC z0fMHoh)g3m+$2NnG}bfKzl-Ga_|Qnzw;t^RU93^inKMpKKg5z6&=XMZpUil)^WK-J z|5%4y(?Z8|5DcL+%8%M>Tu`%k2#juSYo~ifmyR{dyYJo_HwzpI#Vj(lo?BncxuQKl z0Srk4pr%C`%FQ+oP6sxUqIysbLm62EBE=UOrM1F5AG3hX!{F%PKZ5>d$MyuUJq_^7BoQ=-S3 zl*LV23Iy(}&+g#eJ07lz^H4H~2l(CP2LgQt@h^p*n;pOW>CnYdu5HeY%+J2gXW8aVnTUVl(CdNkPOR! z`k%mBTpk4cuvpE7z-0@`NGptgy=G2M{)}$*f&2?1o#X-dui@1t&r_R0(4L!UM zcRPDU?@%?FKH0_bp(vAle?TrKp~EMTF%h4gmNL`FMFN0}4iJ$;J!VM9$I&`x-bpd-u(*&;~0F0gm0jlD^j79+Q|2BQCqV zhH{UXZ8~uQ&FCd1+XT*WaH!RPWvAkrO1rXKA%zMMR7y&oJ$ojvrbV!+NfpuWpjVk1 ztl_j*pcH}@M1mA?^et)=@~m;7+Hjb0>O^1I!LG$9m$|ui-|;CG^k~bFOz^Yb83#QZ zjm4M@OB9Dj^=JjBaCS%Ug|76FtL5%}$JjemzKuCbW@tvnfOos4hNj%4Kn@-qgNiMU z;I|vIk39~Dg6{&ksyy)`@q&tv&2376PzMnuiv3Sq->Ay^c$@1FnYu|K zVGE7&u3uMQIWnY5!KmbcCqd`}qXEMn)VZ!2m$y7+LBwL zNm60$ViJ%byaA|6CnPP(V;Y5oq%6xl{ZYR=M!)aWmGs_$0!XFerA~xs;E#P3xk6Kb zF)Jr>EnP|F-Jtw+vdHC?b6q&NgkKN3z`J)ZgbIuTo2+GrxTy}Px;@l>JwdDFw%@!fWyWf}qC1@rXYvMr-w2fA0LmVa8aZOIIEtMBv_exdhayqddE(yteG4errftobKyd{XOMA%b5LtNK^yhj^axInwL?$3O) z?gf;kYwOR^%vFUL@V->gwp+V>6uTrV~Z2;ufp|8--@`;Ro@)F>O_fUQid#{fDPC$v5#LK zg5@gHV>&Y$zovE{nsVtq$7F83_XTKPtG7;_y`3kb1zJC7Fg`^UZlX@KC0nk&>&)<| zw38;hI;y_y4yyF2_I*5UWuNCPu?21(f}Y&T9Ep+Ii;UViIhn06z2fqFR5I zepo-il_We7LTJr;cJ-rv3qcUY8@IuLuHgx&$O|ra2si%B2F-X#z$b7$jK_ZP=g#tL zIzuj%m~n0V+Lk>1)$~v`$HENw1s;LLSEZLVYO4J69hw0d<(ngE_tN;Bd}v;z?3B&aD5O_=6e)EjU#wLtAWsJ`p< zW-l)m-@Cew49T}F=mP^9aF$F<1U?WvzOq0QJ*?mn1C+{JIoDa${x{#btOU`^G<@+$ z_V|bUTlAiBa6Nw)G(Z-o*W$W2cOBY?$9Y&L0x9y|d{ZESDe?4IsN~2rjo?IOLbyfL zfm7E%5aXO5C2vl1U_)K<~3*#&kGlB&1Z#bKVhUE*rQL6`fE0$vpG)|E{r(XTY#JtT9tXxk$Y z64x_5a6x&TpMqvRq@`;YVywV-m~VTkTlXR+Hw_)UgEfG6>Sp71mMOq3ARLX?e92{^umqfhty8oR{H z_LiNJH(pg=o1vUEFt-FcFhKq~)Eb)oa$=mZmY_!iOG{N7nxOjBVJt7l8x#fN8EGJY zD*NXvQ##gcsGG0u2o#ca%)@vL=p_yIf({d|N3g#z1Tl5*Gi8L^EEsBI?c$ir^Uk~-i{%kk$3mzZrv#PaHgl!VGae-UpTaq2R7^wwC{TLUI+X;6S z1?>YGgm;cd=<*(VF|A#l z$>uhN)b3Njqi*HoQtGHH$<^~383Mz)_qqQ5I#Gg(r_CT-B24IDhpi4u!X>PRS|PGu z+$d_~lTZSv3j0@`&4C0BvoI92l3QPOW}y3fOj|)|EeX|qLqk?I2!9YGKBb^H2|HDd zqxubU3`7(W3-7LlEW5NOFE5-6Dp&&Vb$PWNUF3vW|JrcSc*I0ozQc1tWjPOUaH0x_ zEf>?!1q8K~FA+>I(2Pw}MVOJo51o>>$b9NI-F=o)bLQvq^+FHBy zSRbV;-)9y|ggrli6vAULF0BTk4BM>H-UUSG51T?s^vu`8*KlLR;MBs_Z7a~MVC2b; z=7-PrIsnOod2o*{&?KA!BD=%j&pDa9O~)ZI18~zFqq%}`e|P9K?3Y2z^n7d0h~x%L zDn}*Q?+8bU6+e1(#LH>90&bEQXRW;1+Co6_Q7e=V|N5Id|D4ADPcq8i*X7{&Zc*^?;X`~XWpvoQ*dT!R)wAob zD)7)>pDLXF%%wHPLV+v+$GS)c&X0NfaB%QH8{HV;fT`rAfZT-VE=8G+ZHF^~PN0wH z>>wD#2p{(zgeGMmg>`K5WE#8xh^OB_-w$nM@Ed>HL;BS&f&Or>0`>RjP(HA5|MTUg zTLjPKi0<2;9_v6FA-5a#0K`sBRAEiR2Gc>TVtRs*B%|Xf2nVtuBDWh~L`zy?p}a43 z@ZMcD?yPd_lJL9*_V`0u;-9x_tbYo=6(`aX4I_)iJos3Q?JHpA#z3)N;ybAaHDmzt zq(5;lx#WB82$P-j!lLmT3x^Ha(T5MkGbCPvG0OamY*&g?bfIRRx@~oiWp)Hml4;8V zVsR$`(XN>C1(k|tlkH{uHn}HE-3mg4GXu2gD-H=%^cNdKUX`s=HVsm6Y5^Gngj|S)vWe~7 z!PnR3B2(r_qNVsJDVe}ltG#=t+6C_PEx`3y2Q;T*}+Tm&7XJf&Abq{ z9HYLDAH#I%#cp0=z&<_Zvj6^hr#!ipLD0p%9`OgJ2`U`X(Iu^j&G&?$1p7udoXcg~ zXK=nj_6hzzbpg+$%CoU%UVODrpc{n|0y>q?4{3G*fgBjAV7}LqF%G4(&l9&Zsmicp z;yc%d7yc9na-~r~JM%n2uVNzUki4{o43$wI21aXrLzDu5%rLVt`M}~%h1W%xv=e%OqYp8I7eB0h0-R<_ z%CF1hh#&>g!+P{x28gXZ@zTy@@;DREsh!$2D}xQ@-TiIm`mCt z(aenzdDai0Qtn!acf0oM`L%Ad7nO6}TE$_tI2<%T)R`eqQv$)UIw7v`y_1jW{f)~P z9+CTi8-N!MZ@U3HSyc7n>u)ZCA>vuc1?mfeDF+$uNbY_APZP^H0KL-!9G-CyNn;53 zpT{V6>B1nFf(7tdo@Z};G93SBbsALm031;~RNoIXfZatbNJB5%1XDzo$m?rPt()%I zCZ3Hl30Izt!qGir{l0`4+uR+wBC1fS6&dEBlYjytRtG?N^Lcf}J3wFIbm`<56o7jx z!cxE0rgQ%>Sn9;HM8dC$xRH>jMjIj%z-ZK_|71QLI!HldNo=pEUdjFYVU*P8x?VWl z_r`^ex~=|eX{teaL41<2f;k=u2{yqOfaKi+zYu+>{jH+v|9t2|-^6S=imzJL@O#+{ zGL3iDLaFF|nwP(Zl`0wF7JJ&U1K1q}$EzQ%umiOT$cbgJykdZ&T{de1lx>mF2@ck_ zY4)Ba;4=p=Q?lD*L>~rOzkYy)UA29Zc_M|z%jHs&j?*O`N3%%;I=!0F9t&ojE%Dj| zrPu2o_%!f4eJ#Ecs$lV^Ja}mrG(Aa0AGamkAxn#l1cxG6LE*|tqU?y4CXmdz3~g_- zExLX{O66?Ym8q(Rd4y@bD_)PnsDi4zMA;SpB__!h?HxOiGC20Y_7eTE2S|J%Ex}rt zHCcgtmyyYqj3Mx~dy5h2b-BSh1E-DhBGT)K%WB8RYmqgU)K;j=0Fu^96&2^Aan-ZI zcZth<(KriiG?*-y*-Rlme`j1lSie4IPWa}3jZVLCWfUQHlI+Nu%@mcURAAHNms5G*h;AJMWvqk5Om-UL6w$ii7oJH7D@QJt;PmJ z*%UPR^{fxupQH#AQJ_(Bh*|z_kWQoZtLfKK7J56LQHOG!h&xCAJd8P=bnckC=b%~T z2(Z&=W{G8|+@eTgyHRu6OS|uG6UKGk&R&b|P;X>R?l{eFFgkhOEV~^K?2@8QOxCBI z`E{8~Q<>_mAbATwsr0?B3!5Rtn5=c@1%|P6W_wDX)MQWe6d1z*a`&5r!1cG6y%Uwj z#VXm0jsd16X{MO(y6aZddv%C*ZJ5P?1B@snWt`>C4>Qczv>hEvd|OWlxB_;p~f15p@l-X9o5KdvgCc!_cqK4uo6x?X?r1UWsOYOM}V z6K9|S5G2V}2B({%z<9BV_$9`=*Kn!EX7e7hk9|?5c~=&|1`QBvFKN1T6h#mEdIgzR zI7c&m^Wg2%&1d7*0+WDg#{z9YKZ)FVaazIo6nwbH0<`Hq&OYz>k;i0?lxT@fKrZnWciu*LTI3DuxulD&j@(I-6A1;tlY_IQ1i)s30R_l;$Bq2 zVMK68+4n3kgA7n1DO=Dz$aN8nBq^Kf&+|Bc+Och%+oir=k_>_8obw34RnNCb1Qozv z)yy>{qgcdNX-k`)-1ipm!Ha*5|D1D_@dQ=K)LOqrywX1zHxBBVnf8)_WVu*yEbNw= z7RjfTjF(EHP-3YOI?=@YI?;sktu2=?RSeXlC$FfItH@z#UPJUZ*|I-w7ireqjI>M5 z4$uVR;w_}AegjI$n^oh|36ql*al~@&Hl8#-iTouS8R}1dHzm(!CbKs2ei6AQG}jgD ze4Q4Uu7sNHxdP6&#c33_>SZd}XBPa03Vu^_#*tjh9W9n@8nwFn=aP_MD_iO4&B`*L zcNSpuc>i$zOwV&fS@4y4JM9yb$JHC3Ij64QIvPXQXMCz0X0{5bi=lmoMm}ju^ysXA ziL>sNjiHKg%t>l)hxO)}iv!4J+~?1iah$rzeY$C@nR4u&@N7$Jk3UM~Lh|OCAKzgC z(K$o+S3!0c@FVoE?#~yHjk&pCf|vW8AXpA?(TZFJRc$Xm!^R3=vH%T3_b_lkbD6gC zYfn@r5HSyfj&v7jEa;t4P18?0XTC@$do>2?f?U=D<>^kK^=_z6;e81M+a=@4!04V;)B zKs&9mBcuDmDdwRIq|v$^JCtCe{~Ug<;?v1wvO|KkBcPP};Jpv%}N1UYoSD zmz0L!c*(t7oe2DbC&7|RcEwAx;F&84wdu27w;Nw306~xr^LhK?+ToW>Wd4v%MP#L~ zqot|*%foUdEq7FFtK~v#OYK`04raz9EtaywK2s510M_=HJLrq~_pR#b(lMh35)Qp{ zvb}zJoV4efIDXtjlAAjMXmGS!c@_T*?yQh{+JMMnvG(Kxe6N*xP7K;JoOfK$H1FWS z))OMgwI_`}_+Cs{*8CDyXKaTN3@)6n0Y!zjb~&L(IV3}5koH}N5==$%#GgJXWG_dg>pv<@r)bpZ z(A~Q|4oJFK^Vv7}KTRjwp13uKM23cX+A{Jj%HsgSq9aSz;M}lu3XL+WF2;@+4(_Ttpq)7U>a1MKEElNd05`;{UD`-8hO2QO(^Zp z6(-T4Rf3E59EO7#?`+*G!G#hagqmNlAVZ7N>C+;%UQ~S7hkZP-%-VHmtK;Lmsx*Fo zuo{!C(RDG_xau95BxOyb=wnwTxU&A797sAB{ii;F+1MnCamMI9olSM|`od|oP|1hx zoOjrzYcRCy{g;T(TQtrO;zFGWb88thB4BCi9^6;I1uad%(EU+7_Zi9+y5Md-V`rN? zq4oXQ`AJIt&yBBF@CYmz3&}cdt$IiF6g7we3$tGqs4rsF51~^Fj)RoTxvjxJ_?jzr6J`IbcZVwS zNl*&BvM@JP#@aJ2dAksmDW!)FtmDB2ou-V;D>=QpQw}Pibo1!|K=(0ngYkq+VSFYl z;UBKRz@Zx7%lfuv?sH|C{Ro#{Nlp(C*c+i$$oY{S99;`NblYNtIyfi6Fs5bi@vALB z>)AcMx200Nu$owPdz!d}%`xvcMmwsS#j#h49h=B#k(Gm-vZ3 z$q2G~UiL)^>G&9e47jPji3BCr=Vs=CRss}NF}<=i_$OM02_KDTpNr3w1x_MP(?Gu;_K{Z=B%qLIFJvXQd|J(*YK2iW7a?}F-I|}~^ zkrO+VxSc~QQCVYn&~HIZXeWys9T&lvO=mg}HD~gXmj9@=R75{XxKkcJpdQ#Kb6=em zAG_wh#>$8s%gEG>KYd^4PavC~KU^2{ZPzn9gy^lSTGZgf%c_@uJ><{_em^?zTt-+& z^#(j!^w-Kmh8CFB*q*@S_luio6%L1hQBWH?C^D^AflV!S62jxIHTrdZ@Wf1&1e#Y5nGi>v~&7%FS z`SRBVR#-ws7*J%R9-p>2*YRE2dmRbOs2}2f6B%dUi+J2hXYz84f%xx`U^9J9#1zy9 zFn_xOyZ$(1E?FWa4G)O?2$>Hty15QgH%`z_n|#q9UmKu9Pvy51$JNM<@GT)_<`j#YH!F1AraMG z2PB+Bwfuy2t*<6rN3$URQlw4J!{ ze4$DhMLJr%%FfXuOQ%rLTF6i-+Q-Xu6`R`NM=GpA29y}{E4s$D!90X*@Ff3{+Vpf< zCGhNmg)8F|u7m!;$Tbl@5MyRAwksnn#*(VkHU=*A@o^CETWEUI3tjrybK=j&C&S08 zgbz{qBb<*Eeu_>zd+fB))8X^HiDkA_yX74`f;#;L>oMT?twTokt4;%kSBi+i1Z#ED zG>R5c4HiU9l^_S}&XPd?i8<#l(;6@SKn7dCt* zQhn*Opi(~dH3PF*9JBHi^v?Q;akFpTJCD&AuY|->y{P0vKastK`pDXsV=Ii(^n8o` zQ$cHBn(?S-+vQBsw&H5;XAN}epAmzY%ge|SE9ooqE3h_{IzTiMWzixa)>>h+d^#r9Fz=?}zQE!iyF1m3&tV!78Yz;V1PMlHGEIM}O^+L+} zTd`hxLW~w3f2R=6CVIPewd;Q-U|* zp$@cx977*7-z*^#%6xF+e`K-qa~DAjEU}1wO*IG8F$%fR_B}g5^W#RX#XZ&sTu%WN zoqlFFdj^SD#}D{I2I|0k4tE?5)T#_<)44ProQV`A2oP_Fwjbl#Pw~HyS8(YTdnLSK z<&kgA7>ku1k_iV*>cvt(wdk8)R-F?1=~j?)G*V6GGpb9CY{=V=SPlUnZHNs=b+WZr z9+KEFvOY^;NY7N1HfeJ!q$b&V(GCBrFt;oINscye)GxbvTet|h9>UV@Ja)xk=9Y}? z=ViuH4V3sk{zRYakKDCiyk8z1%mBNAm(#~SlQKL?VO+iBI7@=2tKD4ZgMZZRKp~zr zEJ+_JMylhFvDZG<3^S@AofU$D4*1ezl zoPCeCLMRf)wxoW)Gc;fS?y0jSDw&G-v@@D2X9x9?0PJ&eZse0g$0wcvM%=Pz9-zuC zP=;CqQC80Ua8*NuWPF+f$N~66278o!7LHw~ucgZPzmH8W*NO;R*0d7uuaQz>o`(<) z<|ShuqM{$DWyEAKU{(yYZ~A7mQpRPii60R8X$46K3DR@%E?one>>5`8!q?)_u^}|f zqaPirlaBByaZ<2Cm@bA23Q1ks&QmgpEWhBKwqmuCS^EnkH`)FtNCtL@Z`l&Noxxx) z4W;RSYsq#M#ykv1sBD9y5*xN$W;!d2j zCUXZ*9i9W&-+g{0Yt1Co+<6ZO`t z?z^dxL_@tt1=(a4<9H4A-9=Itoi$mT4SF_s%;6UA+l>|^w>N%=7iW5?KRKuXHTeYT zFoD>PziN@*NMIVA!Q%&BfFRMQdzA#cV!7aTsbzDPIxFQGa$YRlo|-B`4qdMSm^PE; z1sdF7+asbfm){wg)aT$hg*L>{Ot7EmA@c>yat_uIc>=bt?X3g*3~7>87WIv^;@6UR~va_y5w_8_bS$OXSksuJS zh0R_o_a}FdUwZNkNmbz~^tq+Ub%OcnN~m@BgssFI?XIuhh_)+UCP(u(>Z7gonKY6u zz)z)*ubKW{e-H**2_OvUwBP+Br_AIIeY$qOWoq|)THgv&bDb-g<>Ftr|0Tor{4F*T z3G&}1&=!Fel5wo5oA?YcLovU1%`l{3scP8#0yuEhp#yi#v-J0Y+sb>ajAKt!bfdKg zVy)xD{YA}D^+@&Eu?I9>>pqvDhIyqEy#tTfN>yLehQCU2+$j+S%I3TFx3s=Gdt37Q zP6(Y1#-$l-FiX`}F^rOH3SyW0y;q}^JMci>DGieI@2bf?s zLlf4YM4Y}5F3biu@nPqGOy7QujTFi`IZ|HVCQ?3hE42>*-k>4v0T|a_-tl|nc~9aZ zZZX(lVmCAm_fUCi>R2=V1ps{bpZ&)FX&jgbM^~R+cch9^w*iOZlkJz;DjfFJ5YEGK z1*qb1Je4cB1g5IzrkJ1enTMOePC|if{%bRsw(|ckgD!5ry8{~8LOajb^6L~<8+1oWmw)2aafuxs5CaVJ;l3$A7aoi z0Z@5r%EFrzg_gh!=vV8`@qS>Z1B`n48;8zZZ$CUg zwVi+ADuJbpG;S+w>hZ7HJoq|)|1$NM!=Tm~fHfP4q&hXbkR1aVW6@sRf_^^4CqBcc zCSU$HfB6_x0-v6iy0GR(V%zguhyH;iZF2p$H}T&_2mJrIXwby<*AE0~{V!kv{`>pl z|6bznd+z@(_utVa|EKP#|4F=zKXt>Zy)C4GAyEkk)0cqNxhOy}mBq%Y#WAibdi^(l zp<-J+`l^f}pxC5&@BS{k=HH;5RHwgQeqmAS*W%cjAuJ&f<=@Hm8!!K#G4HK$o)rPK z;Sd8MhkmU2uu9-qa@dZ)MemFhY|8c7m~d$nP`OBE+&K7O2%+CAQ!LkGtgA*^;_S2o z`p$!x{fzNjHKd`%lPT@@=@()N-0Z){DE%+kMgJZK^_Q<2N0ZB~{*uhzHigz94+~hD zN?^(n4vt%qfBQOTxlqsm8T5`Wwzs7YG;iV%UOX@K3r%dFH)FE?@s-GbtjpgR5dYod z_CJoqjN5=J)E?IaaXZ%7E2&PKAQ-t*dg6r2-W*H12`sF&5|D~cuEg|u)vwT7fiI#6 z)C7@jv;?pbG%%9!G46Q}tO)OCrdR>by$b+qk_%C607H4d*_mB>%CvJX#EN1op!;S3 zfc(wzuoyM!ra*NU>&cqA$I!G3z$z-zJK0~NpH8?r$SE$BZqkZiM2B{o5$-sUMr9}W zLtj}#rL}1};YHMOOQ?I$mZajkNuq!p^lTK4MiPUzBCA4>EsIc-6P!aJLZP zHxaL*cY00KkAMV@q%GJhtM}hPcBvfzK;wo(PIP!;q$sh^|oS z6Fv3wKaM76w@#Jt*XJK;edaUov}I3_A~Sg3=^8433DOg#Jw+QJ~DLm67Xya<&y?{ooGXXW{$SUU(cZgA{SJ7Bp*==K5zcv^;PB}6xPGi zu48$@XT^$j=$y59HKe#SQ_%my1VUGkfYV4$f__S%L(5ha(*Ua{5D1{=5Xr;7S6tSi z>DvW^5_@f@+2+Bs8W)8q(W3f-mD$$HiSjg;AiQF!Z33Y5H-V8YRbqq&(L@FVEcXH+ zKpaFBF3P_;OpFaQ2Y-NuSK2|0w^ra-INYpV09sk{>y#YBl$5bm zPd<)5n4YQ-`eYe%_km{b>$sF)JB`r5B{ZKy-6~ds1~f;@`sWOQ1{!2%@k5 zEpfd!IbiLu+NyUB5OE)}-*Y-`)?gPdIbc*f9Qh{b1Cy+zwOe%9jgHBT~e5G>o|7q_%qoT~VcV866Rs`Ar zC`f1(QK3)~0~tj`C;=r?Boz=4$vK-*5s*|U8KgkO0)ZkYF_Dx|(Djwc%eN1YBRVIn`@cPN0e|v`A)b ze+Dv5Tx7%jlwHQMFBUFs+XOdt?4un zKcSH#C6L$C{k}!9N3D#F#Rb__x*XLc&8zxI%$YwNEBa+K$g&cSQBQi&!AvH1jEGnW0Z6ck>=4A3zd3A?+pRv`FpL(chb_I?Qec& zXzd!14$1?zQCy}DDruw%y1)?pj<6@-?u}cff4tS~ZQCsO~pVqpc8jx{e03-}{5TnFw9HK}zj(Ji? z%(WEn=uFb@)8HSJR_aL&0Om2t<9Y6(t$GJ{>@4 zhJ3t%29rKyikCZ+oh-;EoN;XXf3WskG}Hwz&TP`E!A0Kw@VJTl-Fxdnn(aBN;Lph? zt7bJ6o3f&X;c!xRYc!h{@b13OCM~QIn)}43dlj41g;f$O`$^%B?ZWLKg^~J zoMW!RqJC(ZF>>X+ItebX$~xD|O^0u(Q%tv`Kj4MQ>^f7xcxtQm41@Ka!^wTReeh`6 zmFE3;CUo^G2JOgrJ03IsnoX9T$7q;PvRu9nY^ZDW_mHCYm!UP>oMweFnv^YS{2ST*hYN>Sv)iO;$8{a??-^aqKYu@O;yiA6`=I^T6@f#6 zi3>aO2TgW>K9yiZUD(mT`0QNi4Fcq4zYq)aj1`GHUGrKmqx8zLm3Y@{UqLo;4_9(I zhh=NJt6sXQ;_cIRdD}ZiHB#nj5v}HR__T~tm>-3E*m38$i~K6Uqz0JVL*VXN_h5E}i`0)Sc3-KC{g_wVDnc>Zjauo;Tq` z^Nv{V+!gEgipiz*dLu>q5QqlWSWnKcr}iHo(*bordJ{>(KccsPP^|D%NAawN`O3C( zOQ?bgyENYuG)hzU27;%cs?D6mV_>RPHPI@YSP zrKtn^^sIpAQWc zRPtLHv*#KaWe|t|tgf@~K5$Gow8gzc=;@aCCED~g#qg;n6A)GR5?l+1UR#HM@|)&M z->>=f&A^Q>h|$}&)~etqJJZ%Z1r);Y2y-y}YZ zvMJryPIst9sxKUb=vj9T)V%V6cq;0;$&n5gc`+z{YJ zP}<@760jzaiB`vI^kHmF5E&i1^y=2Vap2zIj0X^wN%AC+vYo0xJg;)>YMb01mB@jx zyAQN)5e;&x3qQME`fiu1PROFfq|vX&DZ`H+JsJp8P6tl};=;~f?J%Fe&1tk3NYXiy zm*GDANZ5c>sV6E5*2G+UjiF|u5c1PvMGD^JrcSdP0|XXbs?NrYhh3 zcxiGv2!BP#7(zb1bFDQD`(bab@#W?IB0T!RI)be?RJ@kZ%Gs8fUO9z3!3o3 zC`&94&A3u>T9sSV4Fls+jxC)+x#0x3!;Dr>1_%daC1C}ymIk&_uM*E5M%cy;Ts57LfzRcKm2gKEplf#|;ZoZ$5 z5}RiV1F46=CZ1+64!k|yLD>s0zh%lA(9FI5L3Cgj+jaVZRCk@%6>?EbO}LO?(8ldM zrd=BBb?yj^3VO`gD64yp{eu#58;`AX%~1C&gMPh!eDx7fY(l!#huZ8=v~m*tp_mI! zPl@Zj;E|i!D$2zVeoQ;&kXvNOo?fMju@&ls$EaQ4#9;f;>fsWxYf0BPXQVfY@gMzr zE>|#lmCg=fxP;j?Y%B_LVJQo0EkxG=5$=fS!o5x7U*pST*=4SbcI1%%8mwuNdjqyv zON^M)S6qw{+^w93yI<>xI>;`4e=<4Hjx}=oCV-5@#2#nwk@krKspW-bCC~|}Z3tTf zIbQu{<9&kGlu6cRnC5iT9*#B_sTHmk_|#VHp54_`ko`Wc>?O`We=H9?NbaLkt<=(a zNlEOU6xqmmN!MWW6tz5i9GI^Kh0=&-q_SDMHO)i6&?)r+x2zE`34_1LA+SfJ8PRIkA zEsL*~j$DA@gFjxNGV?yrO$V2kTvrH9Xb*Q-eM8_(=yaSB@{VU{2zr*SeO0}E3=DsIM*qOqifX&0`QG~%iyK2`#q1Bbu8CRR9Or)#=kWha@B4qyjCSv?|1L%KcCSs<1%mD0Kc<4Ab!>zXT!}yn~T|GOb z2KtiNe*KH7w;Uo2yfP6cF*@j#-2c2S$x%n`La*c7M<#4m&AU|$eP@4rl?mKGyo>OX zfAb&yH}v*?{VQ?|)~{dhE7@34l6{FV(ve9?X8W-pi=ht({gG4M^53;GYXAuJHSe%@ z*9s7*(|S(sQleL;d7g^mQ07H>0yKQcnI?h=zYxmJ&Bx_P@F(9dGCq^!UuH zl+M#6+jG5(z{pfI4&FCOM^!LdrzpYboC?#p2ncLYPB+*I`nHEawJ-(<>CXmUP1Lar zF`KS4>CbRl8@BF!7#4~^#(VX1uZAlK1b7uQFdVT^I(0(RpR)#5>uTmb-*9zdO+?qU z!_Ft6Kqo)|xO(o{?cy_Cjv%OBoN671TsE}ZA=G_sNYyN69fO|U>DZtfw;iK(Xqnx^ z$793aI7r{D^M&#FL#IH>m=yC~fU_c-F|@LKT=W83rxb9V2fG$K2#j--_GjS+-c!vm zSTqv%>bvWeKP~_GkYh5kaMY>`PUwp~q6uomdXUpQHI?JOCHjkma5bl4XE#s@$V0c} z-d_d4;N1wO5BTYAT$$QVaF+qIMr| zLJKQtF_?b00dbyzFU5KKHe!clcj=kOfd4fx7<#43aJLMNjoSwSJIN|mv9*n6#hR(= z?fYG67TpGDi>|SpMYcplgM<_UJNyF!5apOQRc>;C8$`9clJ6X4H1YaF=y=qSQc@(a zd;0TsF!1MA%(|T~@i<~Ww1(JLdj_|PrnR0oV}aHRR+Z3uTlOH-XlQ!olGzFW)k>{6 z7Ve`D?FMoNjljQ9eI4y&GJ;*urw2+W2Nf2_n<8Dl{@%Ak%~nZHsp?g@%@$UQ#FsNem$x*qSNRZ$s=rxazt@XK4mp+> zk!K4H4wg}G#K7iGPVn|*{w$0mRaU9!`33S&p?w$uw9cyXo9jjwOO=$TvZcYrqMv+X zkqJ*fMIG=vc!bwa)5ruoy>~c?%N>!%=CBQ4Xl;6Wk$v6o4Pb5UqOoV^drxux#azPmuNRDa$?xnQ|9%-dH*JnYD z0b)y9w!$F3uO!J!OF9XA1b!6?G$Xl9%&MDGh~f6TwShD=C=ijfBbt8MFg3Q{BK!?I z7O&}He({B^cUYgu{>Wbe>q(&~iv7Hfrg)bKF+w$XaK&1e71+Z+dF< z+VWdIrAkRex;NmKNUw~VkgS{0Q@b+1Rg3fO!vWh5&m|oqBaGDJgFew8`0C5bLb*NR z$q=yNxlXU|1mN$?nJzM6;SHFj!jG>5#nyA~X0*=(JZ7YCZU$VrxMzl8EAKHje?7h_ zoqfPZsO$VpM!^>@EO?`tv4#rK={f42B_*CSIIgZpYF3R%wi7VR@Rv!8s=SaIMj{)K6BWFv^+iBd;5djo?n+^wv}#EY zhrP6;pKN_@#g`Z<%-%LLA$>M-A;~&Tlz_$hbGRNafFzFg>O!u@+0Z>|E)FIKLKX`V z+qAG%Az_-fSWSL)dxPH4xW1}oy;4QMJUAYy?SpmV1;GWgU!sI51y&IR^wD377EoM= zMFXmR+Rq;WtK+n& ziGGCnR~P^y^<3pU%!2V&U42I_DPL^duT*apcNuxq)&2ajCQK*xZHg!U0XojRTlZ^L zzH@SO8aP;hy2wwR|ItP6cAZ*R1IHN5BFL+SCA1$gDKE{GEsHxoQLMl;I8JKmXoX*C zPS4%&O-sqWVXM>`*ROJv6+>XzIv!7x$w!A;R5a6mke7^s;B47lTtE%tlJ3CQ2%``6 zNNDcraj;Qt!rsh?233b?+0;})L2Pf5?0Z~6Vz{vFhqy7}#|C!dqqM%+{^XjHnJyDo2Ufrx=QIx4&#Hd>&&`6UL+p9@XHZvdG0*{g56zykE z_#)~FtLw0sUmGrPED^dxxt=Ot;bK>jP%laKh3iNZYsFhm>#bM*+tPOqZ*2$Qb z;~ymUfBmO6_Qv7j*amnS=|BNJ58?#tReOo?trO`o0PBf}7I3(up*riw@;*+;)C*5a zk09&QmgZ^M4Ams_SaHku1!pYy>C&)=j#Qw^+0AT2*fM07SLAiq>|XxJXujUo=CKF7 zK~aqq8EfCt&KxT%iv4YevCC4u4;nF3pKF=ZuaS!`gijmO6u}2MA zFT12mvb!#Qxz?@yi`C4za*@J;o!DcuI~F_u;~C@{o@Ao;CNT<-$J(9OCJ{64Igll) zK5)S^5Mfz(u;UPU|99uJ93?IF{d#}#Z>{q2{v5flUj3B*$dws~jt@}|6Y`8MKGlX= zInM%SpHM1@II8cmT}E2u(IP{*vWb9tK5NW%pk6V^HI%MvsMLcy?`BysxkTdmZm(es zAab5l;i}!Nw0O}fV()(A(g|Vo7-)f~if)~Ie1z$4?zRS--Q6BmrIRDgorP-~Bn5yW z8=igZ7(hPwyHE8VAJabTr#x8enYUWM=;{WaHpA~qY&rum-)zLoh$kkyQ0}*+qFBl3 z(Ny5Q9~SIgm?`7aKX`%<=%DvPqmF!Ez4>p3t#Ex?q#Wu|lDIe*AvN6BT0F{v@D z@Zvn1E)FKaSb25~m&K>8T-(MqREtC! zFEjz3R)D+lgLnSPxRi>Jyq;W==DsnTCiHtSv~!n-h!snj+#%$3KJoe zE9xlGyUa*TAYd8ovhgNNoGOFnPBDQFDG7B&IiTTZeN6oazn7;U8 zI3^466&!NN7jm@X2d?!)v$zzf`(Fm74BrtioZ~)v^+k0m78~}WNbztd%P|AnRQ-#1 zBlI1qMr^N`b><^xPXPH&U915_1zbM!1wwlhuG&ix_{JM4UpTn9bGM$D?q& z$(^iL4i{!=2L7k{elzHczk6MuSxAQWVK+6<{h`#4TBB2`p^?0sP&4XY$4iM35LMef zpX15nG@)`VrfK|4g>AvUea1w4rkAd>`}&*j3x5B!!8?|h<{Z!T7X4}r;%wz1PLI&! zOoi*1gpW>w_O|EH-JTQl{n_1CdA8EsX6Lt zqP9bSt#uSX{`Bg$bqwjV!n%DW{jn}6s7RkS>e`*z z^!J?~enEfht~M1v zn4=27N1@6Fu{h#YDS-AD0&{lWAe65-g2&~?Zz`Je(=*B+B9EQvP8v<dA-; z!$i46sMAzd#Yni2tV3|jTgrNF{)C|k$xaQvbmP{Di@jWTME3igfcJk^0d5fVD5&hA zbwh=zDN-`2E|iig(`xmAt(BNfy)ldFZ#@hlW74A??QN2ChDC9sNM{3`g)=}b%%pON zY|NOacZ}qwAJRMM4VQZU8JG1NG+BVVVi#AJPs-~O>_KTN=@LLc)vyUCZ<|7z7*AQ_ z`Q_puF7a3U<%>tUOBCnWw%HY{eZPPxO%PDg#P>}86KHdg* zv`SXdaj(7&GsiQ?j;hL*kD((|wM(AKZ^}oxqLm9zk|r@f4ZD>cJJSQ>q{!ib)s(`S z7l)*F2FF?_7ULUR)*u>{zT0gVb$ckSHaKO~{7k^xW5yv?pkM1<-Aw#2 zVx71c9=g=G*XsOdGJoB*rA6yMmjYvGk}?DCq$Jn*!iAAmXr`(_TNIR zPoM`&$wu`!>{A+@D4bBA0JIb4QFu#^T7D;8b>)z#+f;UH3kFL*F_s)X^DgQrg=DFL z4c9jKwTTXI%O|rURyqz4Q_FFaLzK?L=Mv!}Bg7Np5&~1%T*;ljOX3IjK36>e1dRQU z5)?)t2eY7(Lh=YAVCQ)xoGO`K@QJy-co28+Q z0W>km_x0M@#}eUI^gefGg2P$Ffg}4*Z2D7<`R;>q7y4BehdN69Q4Q7JGpl^tAaxAT z#U=lu3zmx}+a#Xk`|4*+Z}r0_|2IcR@H85 zUkF%Ds$rWl0}oFYKz(1{xLf$vpF=`pCv*b&Au-K0cI{RX1Kn8f%aIdjlWa=#WA-H} zew}tEVdh~`&eQMS=E}B9vNwsB4 z%;mZgnI|HS&00E2R3V`%G+;!!j%a`hD8-FFyxLK$*X=cdS%EvLeKFTZ<*}U0L(1n> zB#`*?Gt#?wy<;m~yglYI&f4VOvjq@XO|YRzAXd70)rg9aN6CKA><}0=ifaf$DNlJ^ zy{-LX(VLK-9{EzQS<}zA)|2B;cvrc237lnpYF z+=QMCrc;VA-xDCq8^bx09Ay)BAHw(`JZ7ZNZ63Y=({G;zfZM-?Ot8|iY{&{PF-DS& zW8GdFNS289KRAouLdc9q?q6up^Y@}f&wrnEiKI9~a}k_J>~ml@5^qeyxs&bZQgPU} zTWYY2kfyPEyXDl-5%ogNR8!1))O<~QX`FKxHjX-287(HuJZtIb>~rt4*mLVgOk=150)Be zhZlv08sLUAPDa?rrGz6^Qhuiy;IOAXOx`_^8T2HtdMEgR&wOItJ0n;&WP-AO z;l88s1=guaqr`qNVxh~6gAs{7aRr>`D9ghWt*~+$B3}U^r(fJk^gyvzR_6NjOZ^= zFax{twFtS0Ba{R-*B9xiZJ!(1)pA>%^xaUcjC8~2Lr0E!<|PHsI6(XBREHOx1kg{f znZ|iVo%8KFXweJ9mX) zZi+#kn7fIHq(Vl)oLu*842vpDz2{9~PKrec##tT=>H+8~_`b-lmCyj8hbe{0vQ-{I zuivTIgtl1I@W>wsgN1gt^}wZeRgQjfY;el_L!qLuhf6vRC-rJFWv&{|5M?}{y8mVJaHePju(hnbs)eQXyblT@gUPC z5i}tCP{ytoi`Nm`?yhmg0AA}FGyEAJHrnyS9UCfZ=**;#M$k0Ygua}x-PDj(M*9-q zzERp}dW&m2$z?s=nO0dy-8s5L&}HLoN7 zkEa?bfm8<^P`elgG59kbA|j}bVm2&);jd(|l%LkZUziJqdPc-4a01d9GFCIyp*>v2v& zV(>5T9}oAPPM$J!)vMuKTtHb`$oU6>2ny(3S0fy}w%fJmlBFlk7W%kaHXQPGlHxz&v#^HQhu-r3@wEl# z;?7BQpGrDvt7@Faz_Z3kB}PJlL*$X~LZ-#1)t&<%zbY5GZy>mS>S;;3hr;2w+q^-w z9LRPGAlq`(McL(9HS8|-Dv#4wrXriC#Ys7;+QY2-$S|gg3*L1ax3(;>DiI?%>8}09 z9}451cKX-yF$yFFEl`>w$!e$Lv1N3zY@()gX=$Y?gEYqM^}B$qD_VW?6)MLld!;>{ z@&@~3J&j~^3&_dzpInaD-H((PwcJ)MyC`%R)%!8jPf_~eB~0PverTy@`>&Wz>9)lK6Fps5$V$B ztkb+IKCOqjNI54Uq+#S!uGAT6&A1*!N>EdKF=;pW((C&ZmKMkKfi+;nvA2QNK<}uo{G84!KWB3q zV=uM~>f3$Vxr&|LCG%IGuO)tE0cMMqFpremU17uAv!&v02lZM{Dcs*`pRE2Ra6Ud9 zCJ{xknO~SR#;MFCxj&r0DO|6fZhGTTH1J524*izkFTT>4?2K=#g?$nw1zEnm&o0d3 zYzB=9Ky!XT`($w8REs_V4*zNK6cx{R?{?4!52kcv?cGEuek&n1NdR>y;Xtpbz9-idCv z*N^EMmr9Y9jjY4D<<|Nw)(eb0%t?@Jst%kN@x{qT0aserQOb*pjE}`E6E$`^AbHw1 z&R^tdr%-n}ZLf&dvoO-t_E&|R8*+YSkTV)vJw|t{ub+aj@EWXru8?*bI1jZoyd#_; z3f%6QdT@lN=TwfZZwB%b^{L=w4b?`wpMf(0@)A1?mET?|La}|RnyDe-adS==iUU&B z)UqM<1B@^=(1Ks!EnOJLBKoESOjasiBm`B%_2UW^u1yjxHGab_?GEJ&_zCPybDmI{ zD4%x-YyjbQy+0PXAQHB$UOctNoo@Esb?*A_a0hhW41%nADu@+)EqC9}0)FobIm0%t z_ol1ow?cWt0+XFdVm(+$PU#E&>*i|@S(b+n+%Dy>RXS<;cC7ccUroFpUvB?CB9@5D zNm3g#s?F{zuKo^&b8-<&$$zSu>)wwh(u-t{t=kScgyrnDw|roCZ*VGLqpts2+Fw`Vgwfnu+XLOhibNOorqEX_`$Z?R)%;(JM+i`lKI* zo6%9vu$41FITFsQ#K{OBytV6#cKa)T)3{aF$#1j?>v4kk%Sfb&+v{r7a(yi%KrSb*B?n(WG8 zyOQfy8u*G-=3>LIwW%KC|E*0WGz1qwPU8Sm-FApIK%1sE5jXn&gm(XwcMDR%P(O@~ zsjcIMJT;+$xuG-x@0FWo?MD4jZ09VjlNf^Pmy|A4fQIka4pY|A4%tAhsey^R z)oiNw(G2V0%^9uVvN34;ei<~v!4{9=nYPCRix&aV`yf^TA$lDken&vMHtaVo$@^~7 z=OfY8o$sCgJ%F4|&uDQkU#sO2R_bmNP zA>ZVJEj)4LrzLLf=zq4vojy&L{PM5J@eM;O$Z^R(mSi-by30@uqH&DWw0NmC(eZ};XMLe}KHqRFMz;G6ruu|z37PGI@#r`&@sB;Qe`Axo=~a~Ua|mveAgydex$*C#<%{Q*&=o;^`!R1PtAmS-^SpDCGa5H4F0R4p~T~Y zIGml^6W|oZ?-4e(DL;Y!qjGaA)ikQ%!6JhRg*IAe@@sY}R+!H%ePm=b{qi8f3{(ha zutZzD!#H^^%*DElqO1n$hhtyb$Df=IJY(;!^>2)5C{%(T$Oq`T(07w|tr#~REeoHo z#pirl4j*3Q8)#SR2ZMFAYvXk;*FIc3(UYYa7a?L;t@o-ET@ec)iE6qdqip(_b<}Ta z2WL^)&IypBg+hP18qQj4cf+~}V~_Li0(f@0_E6qsv)>xm7t!81yBIE_)j@_E0gh`Z zbc$P;Ws!Fg@1G0J55p_18%SZeVvEd`;&~E*4CJ;Ny0n|&ZQ2W)$!7-Im?41x52bcD z)7_Rs+rYYM!Wine|9oOTQigZ=cpkRGB(SFx7Hek>kI!`VO7p$~eU)-l3z2ZOJqraZ zw($?(W{p7LjiLkT&NA{|+(NoJsUW->uoKy0M?QJ6{m4PKB(k867Tu{f=Qa8CJjb0Uswf0B7b{zIiE5!bOFMs^hxkJ! z;H|%C-AK(d5C$BWkml2Pg69kkl1;ixjP-E&=l;SP`qU^yF;&2@00X{{yz~mR6c|4J zwek!gs|HVl7+dlgr{N9-AZ`gV@_Do|3EKK7GH?I-k`Ymx&F@|NS!0Hecd(ypwV@;d zf;{O5i1_Nljn2?&9V8vFzrn-|n5N$=Oi;Y97k3(Xh|(|sw>%{5J^qoLjvQ#|XIc(( z{i`$r!|W6s7CGs|1~xr%L3YkNJwUH_b(Y=~vuLX%zx9vMEiKgs3r)3i>vr>K#KSrT zRkkT(kSsWFySf)xxpxX&0y6O)$rewT- zbVvgt-OrWty|*pUg$rNG^@GlUZ^p{=$auX`XW7F9vcQg^7G|e%!u-l;%4_9T3=Z~A zb)F`1^^Qb&AwrG=u7VFx|9nXFF6z`~QoDJT^H5VTq%YLK4p#$?xvRx@Kr^d_h`Wzv zeXpO5TZ+c$EVs=4?(mwP1J^=|)?De|_AVU7L;=`YYh9U-y4GGrW>s?j`CV3buKiS#bL(cj(ow{^3y{m4aC=C+07C24a>o<{dkgWM}TPkNw!j?EZv11iybI z#6xLcjKy=+zHC707h+9UQr4czH`xOp&s#EdbalBPv!ia3ELV?`|7Ptd5?11eM=~pf z4`9GJxIZl8!XU^_g;|dDtbZTIW;ysNFgpQr80iwDRM`*#?K&g?QNQ80fw0KH#Tgi{ z50N}B{h_@lnTr_?q%&Q(j9A$8N?fIm)9>eh(DMir2S8MmrCH&4x9Q7=I0=nZ$92uI zz-9#??(%n&hF5E+>%pw<(z;c7?0(rVAyRFlxo_M|jN&&Nt>X>4bEc&+|43JJr0>$tH$bBL{T+NJqOh=kz0)V#gB=!fcNL{UW7QohGb3=+={`5|HqPq z69va5A#$5fF>uX0i8KEChn|~US|d9`n@;k>7R7EzW_0X~|IE{Y1>xt_v$yNb!b-Kp zpdNaU?;a~>**~cJmr>V3{m0NELx||LgU^PUQzT6A^n);{L91Zxnw5vq5vGE}fG}mg z1%}Jzq^U`L5j1Qys*f-H4BI>Ncp&hwHU;CQMb zFh&y7{EcxZft@^<5dL-U4;zJG@-AJ!>6s4Q?Glyqa7q%aJ6*_qxycm~&G>B%eXi1n z^*zeg$Nmz=uX9^Od7u_J{Z&Gw@Q5&yBQK=)Xk; zP?xtWcN8nE(dTeTca|+*gK#^J95Ky?#OoY#_x`$BF^}QI!1s~qw27#UeoFqG^pAWe z&l`OT6uwn7THP7gShF|Gf&Wobd{Bd+%#H;I*G_B%CKP}`XSIWklg?~{i81Z?#*W0l zFi@u#eMep{3>+eaA8xKcpBlJ={#XZ(Utwy#n{HY)43*%%nuv^tsEJYNGQ4M(VnCLA zD$B@Np22DVzL`AdPHn7^_QnU&TZXEY*)ia3iXy1uVTPebV`o zZKXwehlTt3_&mS_o_i+h>drJsV8`;G6c7fTLCCE)2hLr{3f8LOsMV|v*KEzqK;W-HRb#a`PDVlHEWvg$`Uv?n_(z<`?YO>1?-po zOgPl%7!DD6I5mUfV=fu(g7SVLEsNz{^jD&6YNh(XUh&IiHuDsxk# zj$Y9l4j7pzJ%tGvE|TnZ;78~#>+qtOoapC!pE!1}Cxm|pV&fCJ$?MYwxw#_nQbS}) zJjLrmCieH5OD}%SW|5zDXJIk0h<}sDyq8!RC+40dtT&z;>Ua|5E~dIHrzPyvDHJdAn;rKP5a@= z&u_6w`ZK(>Aq|=C6PF9h9L>=InxkINu@S)l1BAZ)Ryq&xQ)(g(p!~4f)w^*CX(oIF z{M~>&O>Ln0z6;47iC(drrCF&(_vW7lUyhiMVrI>Svn08y9JP;|NHYDDTj*`p^Wn_>Wv6rE*VTMZGcH+|QL(tP+`Sah74g1g0 zX#dc9WcI$R$@60sFIZ(BZGQ))sFp6xSqTby|B55R2!=r?hiCw0!vBJQDFW1)Ro&k6 z(Ou7lG=6yx{WT)xn+rd!JS2EDzvK4~jowL_|DWE)q2T3pI}JoOnYmK) Q(F;{lP(77?^1_Y(2PRW)6#xJL literal 0 HcmV?d00001 diff --git a/doc/img/ghidra_script_mngr_output.png b/doc/img/ghidra_script_mngr_output.png new file mode 100755 index 0000000000000000000000000000000000000000..6d3024c989933b3e1d95d790e41ee4736e4b0fdc GIT binary patch literal 110986 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

!pvhSVJ)TzmRk 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 Rn#d{AQqw)3t#bYGzX2Ks7p?#R literal 0 HcmV?d00001 diff --git a/doc/img/ghidra_script_mngr_rules.png b/doc/img/ghidra_script_mngr_rules.png new file mode 100755 index 0000000000000000000000000000000000000000..7bce6247d646021d4c61dcfcc477ccd8c43ca28f GIT binary patch literal 112394 zcmeFZcT|&G*Ds2?t$=PpMY=)&k={F~)KC=!q)P|sU20Sm1f&J&RjPF91PF-K5PAy` zib@FqLZlN)avt2e-~HZkzjNL(?)m;X_he9#r(~^X&9!Fv&EH&M4>gr3FVS5hBO{{( zt0-ubk)4YoBRfNN;T&+}@gJh=z`s)-+R6{e%K90wz=uC#>F8ITzaLuiGLq;&2OAPKZkOkdY7ESA<5}h z9k|Lx1WH3e_t$KHSN*W(!~}9;%k5C_4nb2_B-N!-Nm|@=i<_pCq`_mVJ}snPif($7K}M8$%(HVYY@zci6%I=xHog=W z8yA15NE@u-@KB@1isACYPmmRD{aGKa`)HbDN|000SDYF(Cmp9NnnOSHQ$88)im7$) z4PQsOs-mM(4@bFz8IS!|!c_G4##nrdsV z4`Fde++PLub+61mFps)j#oTzrC~u}=pqo772Abho4Si3H;;id!aN_VfYpY>3Bu2Z#Q?^gWMxJ@>w#@gqJ z#M?rN<2FvRa<-O=fI3>4v#2|62U%VJnqB7q|G!m55-|2@+BF9S}#K z&&3a!!Wf^Xl|+e_rk|U=Q|z7o&U<}Myg)Ra`>uIZ&Jzg+t~g^Qc|j=P5A#Qlz5%!93y9#A~KAc!@>8l8;5|-N;#lx1T!wK&fpFX zVhv|~=I}KED}@Ese}o9h_|L#(ULQb$jw&G^vNWHuIV+k+nSVBnn@!G~zgeBod&Th~ zEiN8?suQtdH!@}aHL~&<3SoyKMtVFOL1a_;F?95N6W3l#@r^WKlKyL(mU*X~*Jn==L+DT584jyXq$Xv*_z!u1GV381M9J@#wL$PLry3-xqF>Kc@&9 z3$A;ZWZAve#S7^g)Ys9|weev9@AVwq&TFyk;i+;)gH7%m>SCsw-TfE$H=(( z>D#;&H{mB*IT_y%tBtqIOnI>XQmZejOf_YqWH)1@?F@`;{m;$pmTTE1^Udx5P&Aa? zs82^PPue==Q{C*}J|E7c-28>1?L`ecTu81X)Gc_K@2imUF-ySTBT{F;%^^wwi# zaYOyb^qA57I7PN?@$mRIx7-PlExIb{kk>Qr&p{d7ySqM!(wQe%ltMIX3->KRZsC(G z(KuVZ_!h4y9Hv@ICdwkWOa_k&&yDXa=T>Rd4DZ3MysC9%6LxctI4gawWu?^!(3pe& zeM`hSnpLb|h~9M1kSCGXAlurd9Oql*GAGL;B`I0$>A?{HenKL;Gm^d_Z);mcsm zwPVM>l`*y}+2E-g`8KmCv9kEyZNTpTR+21lE`lQ#%6= zglI97kBeKN zR&p4hFnwx!i8j+?ZKA?vdwD1yc<~{5F^c>*M;-mt)FLF@zPD#hn#p)vawWF2zhm-U zxC$vW`)S%O`e&c!(Fjw26kH<6At;LjW>1n*lW+6Svf|S zlzHv1rE)_}<$aEK*YB6hH0C~XtW?>J4HUxp0*ftL`a=W_pQu^_w?G_+mS{~)O@2v9 z?;od6;k5O2b*($2nO$yhKY7aAyl+9M>6B8%i`md+c*GgLtZzsOa20=j!O|c$| z{gf~gRE>9IPf`eGs!##G{cFzN3+n#iSpjB^C^$&FxMUvs{@BdKy;Y zjWgWZMDnEq#;h}azTnlipt}Hr^wEztIyZRaufC?~<#xS$ZOj@Uv${ZarPTLvPEM5$ zE8rt2+Uh5EP8DPhO;p)NhXgz_%dX8=${EZph;4@)ciD=FuJ0=vQz-e-fmO6})cxtL z<(Gt2$EEDD79JJl#>O<{_6JA;`WHdn;QH-L^ST$h)=6kUj?^R(u>Z;X8$ zTG1*86z|sdh}LSLxRiRTXeoYL{P~Zp$$Gb(%eu?`kr^3Gz={*7vL9iu3Oe>1nNFKg zu>7qWD1@txD;I{If^$4W>XDC4{TLAHir%#>X1B7w`7zaag$Q3}#1Ad6T(rMNLt|fW z-fDb>m4hnMZee)du0Ks8Fzn?_qfhFY^Ou+1??M%zvntR>9my`EABoJht)?D?Z~hw{ zG{;82T5~<%;^7%`MPc*e-YEF{H+DX4XlM|g-Yv_>&VJDuQ&_KUiCxSLi>N*D7dCaq z4#vPDK~~PJVl6`t)x>-~??RQbpRa7wnr$ccRnrQoSINE9Y4ovBPq*agn5sKw@GYv<6FoyyMH~`%k#QVwrD2hWMj|32HX(b);2CYrbV*&z=h)rcP}L$33Q)Fv z+t?A2Tx15Q+NM9P5W&OQ1*q^Xo|*&dM|ms*==YpDp3FWJ)a>f~Cz>%nK0fdw{BfmB zkc6{x6y(&~D1XfgijjCr2KsqY>4Yo(X-@>m@GfJ1rQR;O~_CzDve? z?aA?NtpKO8rp=yaj|WqHyu9P458X9;Gh~c1#SAhX(F(;)hqll6`jX7?iRSwYH~S?p z3_Ob>3103&Y_gikBPvtjY<1MEwI+4Z?PZ{@DnGB@<3?|+2Wyvr%WPBgd~BE01c7$} z^MI*tjcWi2!b_BH_InY|+_)Utr(3L_nrtdXHGJbQDZbe5%@EO1gVnNIS+Q?yF7X&% z_U;=sF-w>A3QurPH>zLtRE}aAseITuI^_^o9yrrjBm80CA^!ZH%r`!R#Tkzp3K}QW zW~0xWnlwon;(=YmwD284M>FecR8R-3J*K4R%}_l@JD ztpTkDvl0=9@qM+8O|PTE6`IY6`&7)(YbuIM$xvAEIaOE6H%Q*b-uLm7TR-CUO$9

d1{I6UiO}nQc_-; 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⩔FbEzRt-}v9bo_@W3mK|{Nx>;A@1}P9U;a?w^ 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%0D*RE2*v-Zgf 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 literal 0 HcmV?d00001 diff --git a/doc/img/ghidra_script_mngr_verbosity.png b/doc/img/ghidra_script_mngr_verbosity.png new file mode 100755 index 0000000000000000000000000000000000000000..ae23246cf941fafba16590e3495e259509e456ff GIT binary patch literal 80857 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 APyhe` literal 0 HcmV?d00001 From 8ed4062cf1a42b93ebd49fb1c341fb4bf6635fb8 Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Mon, 28 Aug 2023 12:13:10 -0600 Subject: [PATCH 32/46] sync rules submodule with upstream --- rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules b/rules index 7685a232d..a20c17da0 160000 --- a/rules +++ b/rules @@ -1 +1 @@ -Subproject commit 7685a232d94acbe7e69addb8bd89d752c9fa27a2 +Subproject commit a20c17da067248a11d097d5bb51a1cc7a63590f5 From 7bd24670744e0a8b13005940effcbeedd364ce34 Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Mon, 28 Aug 2023 12:32:52 -0600 Subject: [PATCH 33/46] remove backend-ghidra from workflows --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9b18f8f62..5a49990b1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ master, backend-ghidra ] + branches: [ master ] pull_request: - branches: [ master, backend-ghidra ] + branches: [ master ] permissions: read-all From 203fc368654b101d49f911c54ef712034e007e0a Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Mon, 28 Aug 2023 12:33:07 -0600 Subject: [PATCH 34/46] cleanup CHANGELOG merge --- CHANGELOG.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6615eb31c..9ff1107c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,6 @@ ## master (unreleased) ### New Features -- ELF: implement file import and export name extractor #1607 #1608 @Aayush-Goel-04 -- bump pydantic from 1.10.9 to 2.1.1 #1582 @Aayush-Goel-04 -- develop script to highlight the features that are not used during matching #331 @Aayush-Goel-04 - ghidra: add entry script helping users run capa against a loaded Ghidra database #1767 @mike-hunhoff ### Breaking Changes @@ -15,6 +12,7 @@ - ### Bug Fixes +- ghidra: fix ints_to_bytes performance #1761 @mike-hunhoff ### capa explorer IDA Pro plugin @@ -57,7 +55,6 @@ Speaking of new rules, we have eight additions, coming from Ronnie, Jakub, Morit - ELF: fix parsing of symtab #1704 @williballenthin - result document: don't use deprecated pydantic functions #1718 @williballenthin - pytest: don't mark IDA tests as pytest tests #1719 @williballenthin -- ghidra: fix ints_to_bytes performance #1761 @mike-hunhoff ### capa explorer IDA Pro plugin - fix unhandled exception when resolving rule path #1693 @mike-hunhoff From a522ae20f1c16fbcdc5a074137aa4844e6cbb19f Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Mon, 28 Aug 2023 12:40:02 -0600 Subject: [PATCH 35/46] update CHANGELOG --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ff1107c5..c7de270e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## master (unreleased) ### New Features +- ghidra: add Ghidra feature extractor and supporting code #1770 @colton-gabertan - ghidra: add entry script helping users run capa against a loaded Ghidra database #1767 @mike-hunhoff ### Breaking Changes @@ -109,8 +110,6 @@ For those that use capa as a library, we've introduced some limited breaking cha - data-manipulation/encoding/xor/covertly-decode-and-write-data-to-windows-directory-using-indirect-calls dan.kelly@mandiant.com - linking/runtime-linking/resolve-function-by-brute-ratel-badger-hash jakub.jozwiak@mandiant.com - - ### Bug Fixes - extractor: add a Binary Ninja test that asserts its version #1487 @xusheng6 - extractor: update Binary Ninja stack string detection after the new constant outlining feature #1473 @xusheng6 From e00608e298c1fe997d71959c003abc16a09b936d Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Mon, 28 Aug 2023 12:19:45 -0700 Subject: [PATCH 36/46] ghidra hotfix: fix ghidrathon download (#1771) * hotfix: fix ghidrathon download --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5a49990b1..309a37a7b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ master ] + branches: [ master, backend-ghidra ] pull_request: - branches: [ master ] + branches: [ master, backend-ghidra ] permissions: read-all @@ -184,7 +184,7 @@ jobs: run : | mkdir ./.github/ghidrathon mkdir -p ~/.ghidra/.ghidra_${{ matrix.ghidra-version }}_PUBLIC/Extensions - wget "https://github.com/mandiant/Ghidrathon/archive/refs/tags/v${{ matrix.ghidrathon-version }}.zip" -O ./.github/ghidrathon/ghidrathon-${{ matrix.ghidrathon-version }}.zip + curl -o ./.github/ghidrathon/ghidrathon-${{ matrix.ghidrathon-version }}.zip "https://codeload.github.com/mandiant/Ghidrathon/zip/refs/tags/v${{ matrix.ghidrathon-version }}" unzip .github/ghidrathon/ghidrathon-${{ matrix.ghidrathon-version }}.zip -d .github/ghidrathon/ workdir=$(pwd) gradle -p ./.github/ghidrathon/Ghidrathon-${{ matrix.ghidrathon-version }}/ -PGHIDRA_INSTALL_DIR=$workdir/.github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC From 6d3f649a0c66a41a6cc5f0d91727aa29434ba930 Mon Sep 17 00:00:00 2001 From: Colton Gabertan <66766340+colton-gabertan@users.noreply.github.com> Date: Mon, 28 Aug 2023 12:21:30 -0700 Subject: [PATCH 37/46] remove backend-ghidra from CI --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 309a37a7b..84fe2110b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ master, backend-ghidra ] + branches: [ master ] pull_request: - branches: [ master, backend-ghidra ] + branches: [ master ] permissions: read-all From f3a2a5958df385326a6a1f71c3fe87d6be4cea51 Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Mon, 28 Aug 2023 13:24:14 -0600 Subject: [PATCH 38/46] fix Ghidra detection --- capa/helpers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/capa/helpers.py b/capa/helpers.py index c1d2ebf5e..38f94b028 100644 --- a/capa/helpers.py +++ b/capa/helpers.py @@ -44,7 +44,11 @@ def is_runtime_ida(): def is_runtime_ghidra(): - return importlib.util.find_spec("ghidra") is not None + try: + currentProgram # type: ignore [name-defined] # noqa: F821 + except NameError: + return False + return True def assert_never(value) -> NoReturn: From 7cc10401d5745dfdd38685fbde851190aee8ed85 Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Mon, 28 Aug 2023 15:15:47 -0600 Subject: [PATCH 39/46] fix #1772 --- capa/features/extractors/ghidra/extractor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py index f68b5dd05..d4439f0f1 100644 --- a/capa/features/extractors/ghidra/extractor.py +++ b/capa/features/extractors/ghidra/extractor.py @@ -44,7 +44,7 @@ def get_functions(self) -> Iterator[FunctionHandle]: for fhandle in ghidra_helpers.get_function_symbols(): fh: FunctionHandle = FunctionHandle( - address=fhandle.getEntryPoint().getOffset(), + address=AbsoluteVirtualAddress(fhandle.getEntryPoint().getOffset()), inner=fhandle, ctx={"imports_cache": self.imports, "externs_cache": self.externs, "fakes_cache": self.fakes}, ) From 0ffd6316060f6ac37aaf279158b87a379ebc560b Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Tue, 29 Aug 2023 09:00:14 -0600 Subject: [PATCH 40/46] Update .github/workflows/tests.yml Co-authored-by: Moritz --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 84fe2110b..5f953949c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,6 +1,6 @@ name: CI -on: +on: push: branches: [ master ] pull_request: From 1fddf800c6307d4f9eea495ecb0328f20fcd1e33 Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Tue, 29 Aug 2023 09:02:46 -0600 Subject: [PATCH 41/46] Update capa/ghidra/README.md Co-authored-by: Moritz --- capa/ghidra/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/capa/ghidra/README.md b/capa/ghidra/README.md index ad7221733..6b9bf2019 100644 --- a/capa/ghidra/README.md +++ b/capa/ghidra/README.md @@ -46,7 +46,7 @@ The syntax is as so: ``` > **Note:** You may add the `$GHIDRA_INSTALL_DIR/support` to your `$PATH` in order to call `analyzeHeadless` as a standalone program. -If you do not have an existing ghidra project, you may also create one with the Headless Analyzer via the `-Import` flag. Post scripts may also be ran in the same invocation. +If you do not have an existing Ghidra project, you may also create one with the Headless Analyzer via the `-Import` flag. Post scripts may also be ran in the same invocation. The syntax to both import a new file and run capa against it is: ```bash From a6e61ed6f13ee5280b60ea09d417fdfa45e582a3 Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Tue, 29 Aug 2023 09:03:26 -0600 Subject: [PATCH 42/46] Update capa/ghidra/README.md Co-authored-by: Moritz --- capa/ghidra/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/capa/ghidra/README.md b/capa/ghidra/README.md index 6b9bf2019..e675132c2 100644 --- a/capa/ghidra/README.md +++ b/capa/ghidra/README.md @@ -134,7 +134,7 @@ INFO ANALYZING changes made by post scripts: /Practical Malware Analysis Lab 01 ### Ghidra's Script Manager To invoke capa from the `Ghidra Script Manager`, open your Ghidra Project's Code Browser and open the `Script Manager` window by navigating to `Window -> Script Manager`. Select `capa_ghidra.py` and run the script. capa will then prompt you to choose a `rules` directory and specify the output verbosity level. -> **Note:** In order for the Script Manager to recognize `capa_ghidra.py` you must either copy it to your Ghidra user scripts directory or update the Script Manager search path to include directory that contains it. +> **Note:** In order for the Script Manager to recognize `capa_ghidra.py` you must either copy it to your Ghidra user scripts directory or update the Script Manager search path to include the directory that contains it.

From 37917b61817c4ff17aa2d46b64e0d97265dfde70 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Tue, 29 Aug 2023 17:28:49 +0000 Subject: [PATCH 43/46] update ghidra feat extractor docs --- capa/ghidra/README.md | 67 +++++++++++++----------------- doc/img/ghidra_console_output.png | Bin 79236 -> 0 bytes 2 files changed, 30 insertions(+), 37 deletions(-) delete mode 100755 doc/img/ghidra_console_output.png diff --git a/capa/ghidra/README.md b/capa/ghidra/README.md index e675132c2..31a9ab2da 100644 --- a/capa/ghidra/README.md +++ b/capa/ghidra/README.md @@ -29,20 +29,39 @@ OR $ capa --version ``` -3. Copy `capa_ghidra.py`, found [here](/capa/ghidra/capa_ghidra.py), to your Ghidra user scripts directory OR manually add `` to the Ghidra Script Manager. +3. Copy `capa_ghidra.py`, found [here](/capa/ghidra/capa_ghidra.py), to your `$USER_HOME/ghidra_scripts` directory OR manually add `` to the Ghidra Script Manager. 1. This entrypoint script is located in `capa_install_dir/capa/ghidra/` -Once Ghidrathon is configured, you may now invoke capa from within Ghidra in three different ways. Each method suits different use cases of capa, and they include Ghidra's `headlessAnalyzer`, `Scripting Console`, and `Script Manger`. +Once Ghidrathon is configured, you may now invoke capa from within Ghidra in two different ways. These include Ghidra's Headless Analyzer and Script Manager. ## Running capa with the Ghidra feature extractor +### Ghidra's Script Manager + +To invoke capa from the `Ghidra Script Manager`, open your Ghidra Project's Code Browser and open the `Script Manager` window by navigating to `Window -> Script Manager`. Select `capa_ghidra.py` and run the script. capa will then prompt you to choose a `rules` directory and specify the output verbosity level. +> **Note:** In order for the Script Manager to recognize `capa_ghidra.py` you must either copy it to your `$USER_HOME/ghidra_scripts` directory or update the Script Manager search path to include the directory that contains it. + +
+ + + +
+ ### Ghidra's Headless Analyzer -To invoke capa headlessly (i.e. without the Ghidra user interface), we must call the `analyzeHeadless` script provided in your `$GHIDRA_INSTALL_DIR/support` and point it towards capa's `capa_ghidra.py`. One thing to note is that capa runs as a `PostScript`, as in post-analysis script, so we need to provide `analyzeHeadless` with the path and script to run against our project. The preferred method for the Ghidra feature extractor is the entrypoint script, `/capa/ghidra/capa_ghidra.py`. Additional capa command line arguments must be provided in a single, space-delimited string i.e. `"/path/to/rules -v"`. To display the help & usage statement, the keyword `help` must be used instead of the typical `-h or --help`. +To invoke capa using the Ghidra Headless Analyzer, you can use Ghidra's `analyzeHeadless` script, located in your `$GHIDRA_INSTALL_DIR/support` directory. + +`analyzeHeadless` requires these arguments to invoke capa: +1. `/path/to/ghidra/project ghidra_project_name` +2. `-process sample.exe_` OR `-Import /path/to/sample/sample.exe_` +3. `-ScriptPath /path/to/capa_ghidra/` +4. `-PostScript capa_ghidra.py` +5. `"/path/to/rules/ "` +> `"/path/to/rules/ "` must be provided in a single, space-delimited string. The help statement, normally accessed via `-h or --help`, must be accessed via the keyword `help` instead. The syntax is as so: ```bash -./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/gpr_dir/ gpr_name -process sample_name.exe_ -ScriptPath /path/to/capa_ghidra.py/ -PostScript capa_ghidra.py "/path/to/capa/rules/" +./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/ghidra/project/ ghidra_project_name -process sample.exe_ -ScriptPath /path/to/capa_ghidra/ -PostScript capa_ghidra.py "/path/to/rules/ -vv" ``` > **Note:** You may add the `$GHIDRA_INSTALL_DIR/support` to your `$PATH` in order to call `analyzeHeadless` as a standalone program. @@ -50,9 +69,14 @@ If you do not have an existing Ghidra project, you may also create one with the The syntax to both import a new file and run capa against it is: ```bash -./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/gpr_dir/ gpr_name -Import /path/to/sample_name.exe_ -ScriptPath /path/to/capa_install/capa/ghidra -PostScript capa_ghidra.py "/path/to/rules/" +./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/ghidra/project/ ghidra_project_name -Import /path/to/sample/sample.exe_ -ScriptPath /path/to/capa_ghidra/ -PostScript capa_ghidra.py "/path/to/rules/" +``` +> **Note:** The `/path/to/ghidra/project/` must exist before importing a new project into it. + +To view the usage and help statement, the syntax is: +```bash +./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/ghidra/project/ ghidra_project_name -process sample.exe_ -ScriptPath /path/to/capa_ghidra/ -PostScript capa_ghidra.py "help" ``` -> **Note:** The `/path/to/gpr_dir/` must exist before importing a new project into it. **Example Output - very verbose flag:** ``` @@ -130,34 +154,3 @@ INFO ANALYZING changes made by post scripts: /Practical Malware Analysis Lab 01 [...] ``` - -### Ghidra's Script Manager - -To invoke capa from the `Ghidra Script Manager`, open your Ghidra Project's Code Browser and open the `Script Manager` window by navigating to `Window -> Script Manager`. Select `capa_ghidra.py` and run the script. capa will then prompt you to choose a `rules` directory and specify the output verbosity level. -> **Note:** In order for the Script Manager to recognize `capa_ghidra.py` you must either copy it to your Ghidra user scripts directory or update the Script Manager search path to include the directory that contains it. - - -
- - - -
- -### Ghidrathon's Script Console - -To invoke capa from Ghidrathon's Script Console, open your Ghidra project's Code Browser and open the `Ghidrathon` window by navigating to `Window -> Ghidrathon`. - -You must import capa into the console and run it via: - -```python3 ->>> import capa ->>> from capa.ghidra import capa_ghidra ->>> capa_ghidra.main() -``` - -Similarly to the Ghidra Script Manager, you will be prompted to choose a capa rules directory and specify output verbosity: - -
- -
- diff --git a/doc/img/ghidra_console_output.png b/doc/img/ghidra_console_output.png deleted file mode 100755 index c40d8811981385bef408a4bd36c72535ce0749b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79236 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 Q(F;{lP(77?^1_Y(2PRW)6#xJL From 0ec682a46451557c10628ebd99426deee6158220 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Tue, 29 Aug 2023 18:01:11 +0000 Subject: [PATCH 44/46] add shellcode documentation & update Headless Analyzer example --- capa/ghidra/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/capa/ghidra/README.md b/capa/ghidra/README.md index 31a9ab2da..42638413c 100644 --- a/capa/ghidra/README.md +++ b/capa/ghidra/README.md @@ -57,7 +57,10 @@ To invoke capa using the Ghidra Headless Analyzer, you can use Ghidra's `analyze 3. `-ScriptPath /path/to/capa_ghidra/` 4. `-PostScript capa_ghidra.py` 5. `"/path/to/rules/ "` -> `"/path/to/rules/ "` must be provided in a single, space-delimited string. The help statement, normally accessed via `-h or --help`, must be accessed via the keyword `help` instead. +> `"/path/to/rules/ "` must be provided in a single, space-delimited string. The help statement, normally accessed via `-h or --help`, must be accessed using the keyword `help` instead. + +To run capa against shellcode, Ghidra will require an additional argument to be passed to the Headless Analyzer. `-processor ` is used to specify the architecture in which Ghidra will process the sample. +> **Note:** More information on specifying the languageID can be found in the `$GHIDRA_INSTALL_DIR/support/analyzeHeadlessREADME.html` documentation. The syntax is as so: ```bash @@ -78,7 +81,7 @@ To view the usage and help statement, the syntax is: ./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/ghidra/project/ ghidra_project_name -process sample.exe_ -ScriptPath /path/to/capa_ghidra/ -PostScript capa_ghidra.py "help" ``` -**Example Output - very verbose flag:** +**Example Output: Shellcode & -vv flag** ``` $ analyzeHeadless /home/wampus test -process Practical\ Malware\ Analysis\ Lab\ 01-01.dll_ -PostScript capa_ghidra.py "/home/wampus/capa/rules -vv" [...] From 72ed4d1165ebe8b643a3a4385933f1bb266dbc80 Mon Sep 17 00:00:00 2001 From: colton-gabertan Date: Tue, 29 Aug 2023 18:05:03 +0000 Subject: [PATCH 45/46] push shellcode example --- capa/ghidra/README.md | 110 ++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/capa/ghidra/README.md b/capa/ghidra/README.md index 42638413c..4ce90d0b1 100644 --- a/capa/ghidra/README.md +++ b/capa/ghidra/README.md @@ -83,77 +83,81 @@ To view the usage and help statement, the syntax is: **Example Output: Shellcode & -vv flag** ``` -$ analyzeHeadless /home/wampus test -process Practical\ Malware\ Analysis\ Lab\ 01-01.dll_ -PostScript capa_ghidra.py "/home/wampus/capa/rules -vv" +$ analyzeHeadless ~/Desktop/ghidra_projects/ capa_test -process 499c2a85f6e8142c3f48d4251c9c7cd6.raw32 -processor x86:LE:32:default -ScriptPath ./capa/ghidra/ -PostScript capa_ghidra.py "./rules -vv" [...] -INFO REPORT: Analysis succeeded for file: /Practical Malware Analysis Lab 01-01.dll_ (HeadlessAnalyzer) -INFO SCRIPT: /ghidra_scripts/capa_ghidra.py (HeadlessAnalyzer) -md5 290934c61de9176ad682ffdd65f0a669 +INFO REPORT: Analysis succeeded for file: /499c2a85f6e8142c3f48d4251c9c7cd6.raw32 (HeadlessAnalyzer) +INFO SCRIPT: /home/wumbo/capa/./capa/ghidra/capa_ghidra.py (HeadlessAnalyzer) +md5 499c2a85f6e8142c3f48d4251c9c7cd6 sha1 -sha256 f50e42c8dfaab649bde0398867e930b86c2a599e8db83b8260393082268f2dba -path /home/spring/Documents/capa/tests/data/Practical Malware Analysis Lab 01-01.dll_ -timestamp 2023-08-25 15:40:39.990986 -capa version 6.0.0 -os windows -format Portable Executable (PE) +sha256 e8e02191c1b38c808d27a899ac164b3675eb5cadd3a8907b0ffa863714000e72 +path /home/wumbo/capa/./tests/data/499c2a85f6e8142c3f48d4251c9c7cd6.raw32 +timestamp 2023-08-29 17:57:00.946588 +capa version 6.1.0 +os unknown os +format Raw Binary arch x86 extractor ghidra base address global -rules /home/spring/Documents/capa/rules -function count 5 +rules /home/wumbo/capa/rules +function count 42 library function count 0 -total feature count 376 +total feature count 1970 -contain loop (3 matches, only showing first match of library rule) +contain loop (24 matches, only showing first match of library rule) author moritz.raabe@mandiant.com scope function -function @ 0x10001010 +function @ 0x0 or: - characteristic: loop @ 0x10001010 - -delay execution (2 matches, only showing first match of library rule) -author michael.hunhoff@mandiant.com, @ramen0x3f -scope basic block -mbc Anti-Behavioral Analysis::Dynamic Analysis Evasion::Delayed Execution [B0003.003] -references https://docs.microsoft.com/en-us/windows/win32/sync/wait-functions, https://github.com/LordNoteworthy/al-khaser/blob/master/al-khaser/TimingAttacks/timing.cpp -basic block @ 0x10001154 in function 0x10001010 - or: - and: - os: windows - or: - api: kernel32.Sleep @ 0x10001159 + characteristic: loop @ 0x0 + characteristic: tight loop @ 0x278 -check mutex -namespace host-interaction/mutex -author moritz.raabe@mandiant.com, anushka.virgaonkar@mandiant.com +contain obfuscated stackstrings +namespace anti-analysis/obfuscation/string/stackstring +author moritz.raabe@mandiant.com scope basic block -mbc Process::Check Mutex [C0043] -basic block @ 0x1000102E in function 0x10001010 - and: - or: - api: kernel32.OpenMutex @ 0x10001059 - -create mutex -namespace host-interaction/mutex -author moritz.raabe@mandiant.com, michael.hunhoff@mandiant.com -scope function -mbc Process::Create Mutex [C0042] -function @ 0x10001010 - or: - api: kernel32.CreateMutex @ 0x1000106E +att&ck Defense Evasion::Obfuscated Files or Information::Indicator Removal from Tools [T1027.005] +mbc Anti-Static Analysis::Executable Code Obfuscation::Argument Obfuscation [B0032.020], Anti-Static Analysis::Executable Code Obfuscation::Stack Strings [B0032.017] +basic block @ 0x0 in function 0x0 + characteristic: stack string @ 0x0 -create process on Windows -namespace host-interaction/process/create +encode data using XOR +namespace data-manipulation/encoding/xor author moritz.raabe@mandiant.com scope basic block -mbc Process::Create Process [C0017] -basic block @ 0x10001179 in function 0x10001010 +att&ck Defense Evasion::Obfuscated Files or Information [T1027] +mbc Defense Evasion::Obfuscated Files or Information::Encoding-Standard Algorithm [E1027.m02], Data::Encode Data::XOR [C0026.002] +basic block @ 0x8AF in function 0x8A1 + and: + characteristic: tight loop @ 0x8AF + characteristic: nzxor @ 0x8C0 + not: = filter for potential false positives + or: + or: = unsigned bitwise negation operation (~i) + number: 0xFFFFFFFF = bitwise negation for unsigned 32 bits + number: 0xFFFFFFFFFFFFFFFF = bitwise negation for unsigned 64 bits + or: = signed bitwise negation operation (~i) + number: 0xFFFFFFF = bitwise negation for signed 32 bits + number: 0xFFFFFFFFFFFFFFF = bitwise negation for signed 64 bits + or: = Magic constants used in the implementation of strings functions. + number: 0x7EFEFEFF = optimized string constant for 32 bits + number: 0x81010101 = -0x81010101 = 0x7EFEFEFF + number: 0x81010100 = 0x81010100 = ~0x7EFEFEFF + number: 0x7EFEFEFEFEFEFEFF = optimized string constant for 64 bits + number: 0x8101010101010101 = -0x8101010101010101 = 0x7EFEFEFEFEFEFEFF + number: 0x8101010101010100 = 0x8101010101010100 = ~0x7EFEFEFEFEFEFEFF + +get OS information via KUSER_SHARED_DATA +namespace host-interaction/os/version +author @mr-tz +scope function +att&ck Discovery::System Information Discovery [T1082] +references https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm +function @ 0x1CA6 or: - api: kernel32.CreateProcess @ 0x100011AF - + number: 0x7FFE026C = NtMajorVersion @ 0x1D18 -Script /ghidra_scripts/capa_ghidra.py called exit with code 0 -INFO ANALYZING changes made by post scripts: /Practical Malware Analysis Lab 01-01.dll_ (HeadlessAnalyzer) +Script /home/wumbo/capa/./capa/ghidra/capa_ghidra.py called exit with code 0 [...] ``` From d17db614b9bf394ae04262f8b97d5feb54ddc5ff Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Wed, 30 Aug 2023 10:33:38 -0600 Subject: [PATCH 46/46] Update README.md --- capa/ghidra/README.md | 97 +++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/capa/ghidra/README.md b/capa/ghidra/README.md index 4ce90d0b1..f1e811953 100644 --- a/capa/ghidra/README.md +++ b/capa/ghidra/README.md @@ -4,93 +4,101 @@ The Ghidra feature extractor is an application of the FLARE team's open-source project, Ghidrathon, to integrate capa with Ghidra using Python 3. capa is a framework that uses a well-defined collection of rules to identify capabilities in a program. You can run capa against a PE file, ELF file, or shellcode and it tells you what it thinks the program can do. For example, it might suggest that the program is a backdoor, can install services, or relies on HTTP to communicate. The Ghidra feature extractor can be used to run capa analysis on your Ghidra databases without needing access to the original binary file. + + ## Getting Started ### Installation +Please ensure that you have the following dependencies installed before continuing: + | Dependency | Version | Source | |------------|---------|--------| | Ghidrathon | `>= 3.0.0` | https://github.com/mandiant/Ghidrathon | | Python | `>= 3.8` | https://www.python.org/downloads | | Ghidra | `>= 10.2` | https://ghidra-sre.org | -In order to run capa using the Ghidra feature extractor, you must install capa as a library and obtain the official capa rules that match the version you have installed. You can do this by completing the following steps using the Python 3 interpreter that you have configured for your Ghidrathon installation: +In order to run capa using using Ghidra, you must install capa as a library, obtain the official capa rules that match the capa version you have installed, and configure the Python 3 script [capa_ghidra.py](/capa/ghidra/capa_ghidra.py). You can do this by completing the following steps using the Python 3 interpreter that you have configured for your Ghidrathon installation: -1. Install capa and its dependencies from PyPI: +1. Install capa and its dependencies from PyPI using the following command: ```bash $ pip install flare-capa ``` -2. Download and extract the [official capa rules](https://github.com/mandiant/capa-rules/releases) that match the version you have installed - 1. Use the following command to view the version of capa you have installed: +2. Download and extract the [official capa rules](https://github.com/mandiant/capa-rules/releases) that match the capa version you have installed. Use the following command to view the version of capa you have installed: ```bash $ pip show flare-capa OR $ capa --version ``` -3. Copy `capa_ghidra.py`, found [here](/capa/ghidra/capa_ghidra.py), to your `$USER_HOME/ghidra_scripts` directory OR manually add `` to the Ghidra Script Manager. - 1. This entrypoint script is located in `capa_install_dir/capa/ghidra/` +3. Copy [capa_ghidra.py](/capa/ghidra/capa_ghidra.py) to your `$USER_HOME/ghidra_scripts` directory or manually add `` to the Ghidra Script Manager. -Once Ghidrathon is configured, you may now invoke capa from within Ghidra in two different ways. These include Ghidra's Headless Analyzer and Script Manager. +## Usage -## Running capa with the Ghidra feature extractor +After completing the installation steps you can execute `capa_ghidra.py` using the Ghidra Script Manager or Headless Analyzer. -### Ghidra's Script Manager +### Ghidra Script Manager -To invoke capa from the `Ghidra Script Manager`, open your Ghidra Project's Code Browser and open the `Script Manager` window by navigating to `Window -> Script Manager`. Select `capa_ghidra.py` and run the script. capa will then prompt you to choose a `rules` directory and specify the output verbosity level. -> **Note:** In order for the Script Manager to recognize `capa_ghidra.py` you must either copy it to your `$USER_HOME/ghidra_scripts` directory or update the Script Manager search path to include the directory that contains it. +To execute `capa_ghidra.py` using the Ghidra Script Manager, first open the Ghidra Script Manager by navigating to `Window > Script Manager` in the Ghidra Code Browser. Next, locate `capa_ghidra.py` by selecting the `Python 3 > capa` category or using the Ghidra Script Manager search funtionality. Finally, double-click `capa_ghidra.py` to execute the script. If you don't see `capa_ghidra.py`, make sure you have copied the script to your `$USER_HOME/ghidra_scripts` directory or manually added `` to the Ghidra Script Manager -
- - - -
+When executed, `capa_ghidra.py` asks you to provide your capa rules directory and preferred output format. `capa_ghidra.py` supports `default`, `verbose`, and `vverbose` output formats when executed from the Ghidra Script Manager. `capa_ghidra.py` writes output to the Ghidra Console Window. -### Ghidra's Headless Analyzer +#### Example -To invoke capa using the Ghidra Headless Analyzer, you can use Ghidra's `analyzeHeadless` script, located in your `$GHIDRA_INSTALL_DIR/support` directory. +The following is an example of running `capa_ghidra.py` using the Ghidra Script Manager: -`analyzeHeadless` requires these arguments to invoke capa: -1. `/path/to/ghidra/project ghidra_project_name` -2. `-process sample.exe_` OR `-Import /path/to/sample/sample.exe_` -3. `-ScriptPath /path/to/capa_ghidra/` -4. `-PostScript capa_ghidra.py` -5. `"/path/to/rules/ "` -> `"/path/to/rules/ "` must be provided in a single, space-delimited string. The help statement, normally accessed via `-h or --help`, must be accessed using the keyword `help` instead. +Selecting capa rules: + -To run capa against shellcode, Ghidra will require an additional argument to be passed to the Headless Analyzer. `-processor ` is used to specify the architecture in which Ghidra will process the sample. -> **Note:** More information on specifying the languageID can be found in the `$GHIDRA_INSTALL_DIR/support/analyzeHeadlessREADME.html` documentation. +Choosing output format: + -The syntax is as so: -```bash -./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/ghidra/project/ ghidra_project_name -process sample.exe_ -ScriptPath /path/to/capa_ghidra/ -PostScript capa_ghidra.py "/path/to/rules/ -vv" +Viewing results in Ghidra Console Window: + + +### Ghidra Headless Analyzer + +To execute `capa_ghidra.py` using the Ghidra Headless Analyzer, you can use the Ghidra `analyzeHeadless` script located in your `$GHIDRA_HOME/support` directory. You will need to provide the following arguments to the Ghidra `analyzeHeadless` script: + +1. ``: path to Ghidra project +2. ``: name of Ghidra Project +3. `-process `: name of sample `` +4. `-ScriptPath `: OPTIONAL argument specifying path `` to `capa_ghidra.py` +5. `-PostScript capa_ghidra.py`: executes `capa_ghidra.py` as post-analysis script +6. `""`: single, quoted string containing capa arguments that must specify capa rules directory and output format, e.g. `" --verbose"`. `capa_ghidra.py` supports `default`, `verbose`, `vverbose` and `json` formats when executed using the Ghidra Headless Analyzer. `capa_ghidra.py` writes output to the console window used to execute the Ghidra `analyzeHeadless` script. +7. `-processor `: required ONLY if sample `` is shellcode. More information on specifying the `` can be found in the `$GHIDRA_HOME/support/analyzeHeadlessREADME.html` documentation. + +The following is an example of combining these arguments into a single `analyzeHeadless` script command: + +``` +$GHIDRA_HOME/support/analyzeHeadless -process -PostScript capa_ghidra.py "/path/to/capa/rules/ --verbose" ``` -> **Note:** You may add the `$GHIDRA_INSTALL_DIR/support` to your `$PATH` in order to call `analyzeHeadless` as a standalone program. -If you do not have an existing Ghidra project, you may also create one with the Headless Analyzer via the `-Import` flag. Post scripts may also be ran in the same invocation. +You may also want to run capa against a sample that you have not yet imported into your Ghidra project. The following is an example of importing a sample and running `capa_ghidra.py` using a single `analyzeHeadless` script command: -The syntax to both import a new file and run capa against it is: -```bash -./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/ghidra/project/ ghidra_project_name -Import /path/to/sample/sample.exe_ -ScriptPath /path/to/capa_ghidra/ -PostScript capa_ghidra.py "/path/to/rules/" ``` -> **Note:** The `/path/to/ghidra/project/` must exist before importing a new project into it. +$GHIDRA_HOME/support/analyzeHeadless -Import -PostScript capa_ghidra.py "/path/to/capa/rules/ --verbose" +``` -To view the usage and help statement, the syntax is: -```bash -./$GHIDRA_INSTALL_DIR/support/analyzeHeadless /path/to/ghidra/project/ ghidra_project_name -process sample.exe_ -ScriptPath /path/to/capa_ghidra/ -PostScript capa_ghidra.py "help" +You can also provide `capa_ghidra.py` the single argument `"help"` to view supported arguments when running the script using the Ghidra Headless Analyzer: ``` +$GHIDRA_HOME/support/analyzeHeadless -process -PostScript capa_ghidra.py "help" +``` + +#### Example -**Example Output: Shellcode & -vv flag** +The following is an example of running `capa_ghidra.py` against a shellcode sample using the Ghidra `analyzeHeadless` script: ``` -$ analyzeHeadless ~/Desktop/ghidra_projects/ capa_test -process 499c2a85f6e8142c3f48d4251c9c7cd6.raw32 -processor x86:LE:32:default -ScriptPath ./capa/ghidra/ -PostScript capa_ghidra.py "./rules -vv" +$ analyzeHeadless /home/wumbo/Desktop/ghidra_projects/ capa_test -process 499c2a85f6e8142c3f48d4251c9c7cd6.raw32 -processor x86:LE:32:default -PostScript capa_ghidra.py "/home/wumbo/capa/rules -vv" [...] + INFO REPORT: Analysis succeeded for file: /499c2a85f6e8142c3f48d4251c9c7cd6.raw32 (HeadlessAnalyzer) -INFO SCRIPT: /home/wumbo/capa/./capa/ghidra/capa_ghidra.py (HeadlessAnalyzer) +INFO SCRIPT: /home/wumbo/ghidra_scripts/capa_ghidra.py (HeadlessAnalyzer) md5 499c2a85f6e8142c3f48d4251c9c7cd6 sha1 sha256 e8e02191c1b38c808d27a899ac164b3675eb5cadd3a8907b0ffa863714000e72 -path /home/wumbo/capa/./tests/data/499c2a85f6e8142c3f48d4251c9c7cd6.raw32 +path /home/wumbo/capa/tests/data/499c2a85f6e8142c3f48d4251c9c7cd6.raw32 timestamp 2023-08-29 17:57:00.946588 capa version 6.1.0 os unknown os @@ -158,6 +166,7 @@ function @ 0x1CA6 -Script /home/wumbo/capa/./capa/ghidra/capa_ghidra.py called exit with code 0 +Script /home/wumbo/ghidra_scripts/capa_ghidra.py called exit with code 0 + [...] ```