Compare commits

...

4059 Commits

Author SHA1 Message Date
Moritz
ec1ddb506c Merge pull request #1893 from mrexodia/dex-support
Initial plumbing to support DEX files
2024-01-31 12:03:23 +01:00
Capa Bot
f229c8ecb8 Sync capa rules submodule 2023-12-13 11:04:32 +00:00
Capa Bot
e3da2d88d0 Sync capa rules submodule 2023-12-11 16:07:10 +00:00
Capa Bot
e4eb4340b1 Sync capa rules submodule 2023-12-09 06:53:06 +00:00
Capa Bot
a8e7611252 Sync capa rules submodule 2023-12-08 21:41:12 +00:00
aaronatp
8531acd7c5 Only show stack trace in debug mode (#1860)
* Only show stack trace in dev mode

* Update custom exception handler to handle KeyboardInterrupts
2023-12-08 22:07:16 +01:00
Duncan Ogilvie
e2f655428e Differentiate between function-name and import for DEX 2023-12-08 01:12:48 +01:00
Duncan Ogilvie
b5a4d766d9 Add string features for DEX and clean up method handling 2023-12-08 00:15:20 +01:00
Duncan Ogilvie
b77103a646 Mark DEX methods without code as library functions 2023-12-08 00:15:20 +01:00
Duncan Ogilvie
036f147df8 Support function-name, class, namespace for DEX 2023-12-08 00:15:20 +01:00
Duncan Ogilvie
52d20d2f46 Combine DEX feature extraction into a single class 2023-12-08 00:15:19 +01:00
Duncan Ogilvie
e90be5a9bb Initial plumbing to support DEX files 2023-12-08 00:15:16 +01:00
Mike Hunhoff
d6f7d2180f dotnet: combine dnfile_.py and dotnetfile.py (#1895) 2023-12-07 14:06:54 -07:00
Moritz
d1b213aaac Merge pull request #1890 from mandiant/fix-dlls
fix symbol generation, ordinals
2023-12-03 21:05:01 +01:00
mr-tz
51ddadbc87 fix symbol generation, ordinals 2023-12-03 17:49:54 +02:00
Moritz
cd52b1937b Merge pull request #1887 from mandiant/fix/dynamic/1882
dynamic: fix UnboundLocalError exception
2023-12-01 14:52:55 +01:00
Mike Hunhoff
ca14dab804 dynamic: fix UnboundLocalError exception 2023-11-30 14:52:18 -07:00
Moritz
fbe0440361 add build for Python 3.11 for linux (#1877)
* add build for Python 3.11 for linux
2023-11-29 22:42:56 +01:00
Moritz
4c3586b5e9 Merge pull request #1697 from mandiant/dynamic-feature-extraction
add dynamic analysis
2023-11-29 17:45:24 +01:00
mr-tz
47019e4d7c Merge branch 'master' into dynamic-feature-extraction 2023-11-29 16:28:12 +01:00
Capa Bot
a236a952bc Sync capa rules submodule 2023-11-29 15:24:54 +00:00
mr-tz
73ea822123 Merge branch 'master' into dynamic-feature-extraction 2023-11-29 16:17:09 +01:00
Willi Ballenthin
3c159a1f52 ci: revert temporary CI event subscription 2023-11-29 14:26:53 +00:00
Capa Bot
7db40c3af8 Sync capa rules submodule 2023-11-29 13:53:18 +00:00
Willi Ballenthin
9a996d07c7 Merge branch 'dynamic-feature-extraction' of public.github.com:mandiant/capa into dynamic-feature-extraction 2023-11-29 13:46:47 +00:00
Willi Ballenthin
93cfb6ef8c sync testfiles submodule 2023-11-29 13:46:29 +00:00
Capa Bot
a29c320f95 Sync capa-testfiles submodule 2023-11-29 13:45:44 +00:00
Capa Bot
277d7e0687 Sync capa rules submodule 2023-11-29 13:33:01 +00:00
Yacine
e66c2efcf5 add documentation for dynamic capa capabilties (#1837)
* README: adapt for dynamic capa

* README.md: fix duplication error

* Update README.md

Co-authored-by: Moritz <mr-tz@users.noreply.github.com>

* documentation: add review suggestions

* documentation: newline fix

* Update README.md

Co-authored-by: Moritz <mr-tz@users.noreply.github.com>

* Update README.md

Co-authored-by: Moritz <mr-tz@users.noreply.github.com>

* Update README.md

Co-authored-by: Moritz <mr-tz@users.noreply.github.com>

---------

Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-11-29 14:26:29 +01:00
Willi Ballenthin
583f8b5688 Merge branch 'dynamic-feature-extraction' of public.github.com:mandiant/capa into dynamic-feature-extraction 2023-11-29 13:13:04 +00:00
Willi Ballenthin
b4c6bf859e changelog 2023-11-29 13:12:30 +00:00
Moritz
ba9da0dd82 Merge pull request #1876 from mandiant/fix/1867
set os, arch, format in meta table
2023-11-29 13:44:43 +01:00
mr-tz
92770dd5c7 set os, arch, format in meta table 2023-11-28 17:09:14 +01:00
Moritz
8946cb633e Merge pull request #1874 from mandiant/fix/global-features
only check and display file limitation once
2023-11-28 15:19:10 +01:00
mr-tz
8f0eb5676e only check and display file limitation once 2023-11-28 15:00:47 +01:00
Willi Ballenthin
cb1a037502 Merge pull request #1869 from mandiant/dependabot/pip/flake8-encodings-0.5.1
build(deps-dev): bump flake8-encodings from 0.5.0.post1 to 0.5.1
2023-11-28 12:38:19 +00:00
dependabot[bot]
c8d0071443 build(deps-dev): bump flake8-encodings from 0.5.0.post1 to 0.5.1
Bumps [flake8-encodings](https://github.com/python-formate/flake8-encodings) from 0.5.0.post1 to 0.5.1.
- [Release notes](https://github.com/python-formate/flake8-encodings/releases)
- [Commits](https://github.com/python-formate/flake8-encodings/compare/v0.5.0.post1...v0.5.1)

---
updated-dependencies:
- dependency-name: flake8-encodings
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-28 12:37:42 +00:00
Willi Ballenthin
e6b8a3e505 Merge pull request #1870 from mandiant/dependabot/pip/wcwidth-0.2.12
build(deps-dev): bump wcwidth from 0.2.10 to 0.2.12
2023-11-28 12:37:16 +00:00
Willi Ballenthin
f328df1bc4 Merge pull request #1871 from mandiant/dependabot/pip/setuptools-69.0.2
build(deps-dev): bump setuptools from 68.0.0 to 69.0.2
2023-11-28 12:37:06 +00:00
Willi Ballenthin
d1aa1557b2 Merge pull request #1872 from mandiant/dependabot/pip/flake8-bugbear-23.11.26
build(deps-dev): bump flake8-bugbear from 23.9.16 to 23.11.26
2023-11-28 12:36:58 +00:00
Willi Ballenthin
a0929124ec Merge pull request #1873 from mandiant/dependabot/pip/mypy-1.7.1
build(deps-dev): bump mypy from 1.7.0 to 1.7.1
2023-11-28 12:36:47 +00:00
dependabot[bot]
84ed6c8d24 build(deps-dev): bump mypy from 1.7.0 to 1.7.1
Bumps [mypy](https://github.com/python/mypy) from 1.7.0 to 1.7.1.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.7.0...v1.7.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-27 14:56:45 +00:00
dependabot[bot]
61c8e30f65 build(deps-dev): bump flake8-bugbear from 23.9.16 to 23.11.26
Bumps [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) from 23.9.16 to 23.11.26.
- [Release notes](https://github.com/PyCQA/flake8-bugbear/releases)
- [Commits](https://github.com/PyCQA/flake8-bugbear/compare/23.9.16...23.11.26)

---
updated-dependencies:
- dependency-name: flake8-bugbear
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-27 14:56:29 +00:00
dependabot[bot]
6a4994f1ef build(deps-dev): bump setuptools from 68.0.0 to 69.0.2
Bumps [setuptools](https://github.com/pypa/setuptools) from 68.0.0 to 69.0.2.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v68.0.0...v69.0.2)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-27 14:56:01 +00:00
dependabot[bot]
fce105060d build(deps-dev): bump wcwidth from 0.2.10 to 0.2.12
Bumps [wcwidth](https://github.com/jquast/wcwidth) from 0.2.10 to 0.2.12.
- [Release notes](https://github.com/jquast/wcwidth/releases)
- [Commits](https://github.com/jquast/wcwidth/compare/0.2.10...0.2.12)

---
updated-dependencies:
- dependency-name: wcwidth
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-27 14:55:45 +00:00
Moritz
d84457eac7 Merge pull request #1868 from mandiant/fix/global-features
Fix global features and display
2023-11-27 14:06:01 +01:00
mr-tz
890c879e7c only check and display file limitation once 2023-11-27 13:28:36 +01:00
mr-tz
f201ef1d22 actually get global feature values 2023-11-27 13:28:06 +01:00
Moritz
f763d14266 Merge pull request #1862 from mandiant/dependabot/pip/wcwidth-0.2.10
build(deps-dev): bump wcwidth from 0.2.9 to 0.2.10
2023-11-23 12:28:16 +01:00
Moritz
6f0be06f86 Merge pull request #1861 from mandiant/dependabot/pip/ruff-0.1.6
build(deps-dev): bump ruff from 0.1.5 to 0.1.6
2023-11-23 12:28:05 +01:00
Capa Bot
347687579c Sync capa rules submodule 2023-11-22 18:05:52 +00:00
Capa Bot
d61d1dc591 Sync capa rules submodule 2023-11-22 13:10:44 +00:00
Capa Bot
235a3bede0 Sync capa rules submodule 2023-11-21 10:52:38 +00:00
dependabot[bot]
cf35d2c497 build(deps-dev): bump wcwidth from 0.2.9 to 0.2.10
Bumps [wcwidth](https://github.com/jquast/wcwidth) from 0.2.9 to 0.2.10.
- [Release notes](https://github.com/jquast/wcwidth/releases)
- [Commits](https://github.com/jquast/wcwidth/compare/0.2.9...0.2.10)

---
updated-dependencies:
- dependency-name: wcwidth
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-20 14:20:59 +00:00
dependabot[bot]
f6048b9e99 build(deps-dev): bump ruff from 0.1.5 to 0.1.6
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.5 to 0.1.6.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.1.5...v0.1.6)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-20 14:20:47 +00:00
Capa Bot
9d1e60d4a2 Sync capa-testfiles submodule 2023-11-20 11:40:22 +00:00
Capa Bot
fb1235d26f Sync capa rules submodule 2023-11-20 10:27:11 +00:00
Capa Bot
3fe2328bd2 Sync capa rules submodule 2023-11-17 23:27:52 +00:00
Willi Ballenthin
647abb669f Merge pull request #1858 from doomedraven/patch-1 2023-11-16 14:16:16 +01:00
doomedraven
a5e1eca8cc Create pip-audit.yml 2023-11-16 13:27:25 +01:00
Willi Ballenthin
fdb96709ae Merge pull request #1856 from doomedraven/patch-1
fix pydantic vuln (ReDoS)
2023-11-16 13:20:01 +01:00
doomedraven
490271e50b fix pydantic vuln (ReDoS)
Regular Expression Denial of Service (ReDoS)
MEDIUM SEVERITY
Package Manager: pip
Vulnerable module: pydantic
Remediation
Upgrade pydantic to version 1.10.13, 2.4.0 or higher.
2023-11-16 10:54:59 +01:00
Willi Ballenthin
a870c92a2f sync submodule rules 2023-11-15 11:00:51 +00:00
Willi Ballenthin
de5f08871e sync submodule rules 2023-11-15 10:57:16 +00:00
Capa Bot
2f60ec03af Sync capa rules submodule 2023-11-15 09:25:02 +00:00
Willi Ballenthin
987eb2d358 sync rules submodule 2023-11-14 14:34:08 +00:00
Willi Ballenthin
6e3fff4bae use latest rules migration 2023-11-14 14:29:34 +00:00
Willi Ballenthin
a705bf9eab Merge pull request #1825 from mandiant/fix/issue-1816
verbose: show process name and other human-level details
2023-11-14 12:33:41 +01:00
Willi Ballenthin
c68c68d5cb Merge branch 'dynamic-feature-extraction' into fix/issue-1816 2023-11-14 11:36:24 +01:00
Willi Ballenthin
82013f0e24 submodule: tests: data: sync 2023-11-14 10:35:18 +00:00
Willi Ballenthin
210a13d94e Merge pull request #1850 from mandiant/dependabot/pip/mypy-1.7.0
build(deps-dev): bump mypy from 1.6.1 to 1.7.0
2023-11-14 11:29:59 +01:00
dependabot[bot]
0d5ff45c76 build(deps-dev): bump mypy from 1.6.1 to 1.7.0
Bumps [mypy](https://github.com/python/mypy) from 1.6.1 to 1.7.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.6.1...v1.7.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-14 10:29:20 +00:00
Willi Ballenthin
11b98cb0b1 Merge pull request #1849 from mandiant/dependabot/pip/black-23.11.0
build(deps-dev): bump black from 23.10.1 to 23.11.0
2023-11-14 11:29:12 +01:00
dependabot[bot]
3c9ab63521 build(deps-dev): bump black from 23.10.1 to 23.11.0
Bumps [black](https://github.com/psf/black) from 23.10.1 to 23.11.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.10.1...23.11.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-14 10:29:05 +00:00
Willi Ballenthin
a2fde921aa Merge pull request #1848 from mandiant/dependabot/pip/ruff-0.1.5
build(deps-dev): bump ruff from 0.1.4 to 0.1.5
2023-11-14 11:28:25 +01:00
Willi Ballenthin
d4f7c77be8 Merge pull request #1847 from mandiant/dependabot/pip/pyinstaller-6.2.0
build(deps-dev): bump pyinstaller from 6.1.0 to 6.2.0
2023-11-14 11:28:08 +01:00
dependabot[bot]
f0f95824ac build(deps-dev): bump ruff from 0.1.4 to 0.1.5
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.4 to 0.1.5.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.1.4...v0.1.5)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-13 14:21:13 +00:00
dependabot[bot]
0ba5c23847 build(deps-dev): bump pyinstaller from 6.1.0 to 6.2.0
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 6.1.0 to 6.2.0.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v6.1.0...v6.2.0)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-13 14:20:52 +00:00
Moritz
dee0aa73eb Merge pull request #1844 from mandiant/mr-tz-patch-1
fix whitespace removal in format check
2023-11-11 19:53:44 +01:00
Moritz
41a397661f fix whitespace removal in format check 2023-11-10 11:40:55 +01:00
Moritz
52997e70a0 fix imports according to ruff 2023-11-08 16:58:40 +01:00
Moritz
1acc2d1959 Merge branch 'dynamic-feature-extraction' into fix/issue-1816 2023-11-08 16:56:05 +01:00
Moritz
74f70856a6 Merge pull request #1840 from mandiant/dependabot/pip/wcwidth-0.2.9
build(deps-dev): bump wcwidth from 0.2.8 to 0.2.9
2023-11-08 15:38:27 +01:00
Moritz
e5b7ee96fc Merge pull request #1839 from mandiant/dependabot/pip/black-23.10.1
build(deps-dev): bump black from 23.10.0 to 23.10.1
2023-11-08 15:38:02 +01:00
Moritz
92d43f5327 Merge pull request #1838 from mandiant/dependabot/pip/ruamel-yaml-0.18.5
build(deps-dev): bump ruamel-yaml from 0.18.3 to 0.18.5
2023-11-08 15:37:31 +01:00
dependabot[bot]
48abd297a8 build(deps-dev): bump black from 23.10.0 to 23.10.1
Bumps [black](https://github.com/psf/black) from 23.10.0 to 23.10.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.10.0...23.10.1)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 13:16:09 +00:00
Willi Ballenthin
d64a10a287 Merge pull request #1841 from mandiant/dependabot/pip/ruff-0.1.4
build(deps-dev): bump ruff from 0.0.291 to 0.1.4
2023-11-07 14:15:24 +01:00
dependabot[bot]
abf83fe8cf build(deps-dev): bump ruff from 0.0.291 to 0.1.4
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.291 to 0.1.4.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.291...v0.1.4)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 14:42:18 +00:00
dependabot[bot]
6380d936ae build(deps-dev): bump wcwidth from 0.2.8 to 0.2.9
Bumps [wcwidth](https://github.com/jquast/wcwidth) from 0.2.8 to 0.2.9.
- [Release notes](https://github.com/jquast/wcwidth/releases)
- [Commits](https://github.com/jquast/wcwidth/compare/0.2.8...0.2.9)

---
updated-dependencies:
- dependency-name: wcwidth
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 14:42:06 +00:00
dependabot[bot]
18ab8d28d9 build(deps-dev): bump ruamel-yaml from 0.18.3 to 0.18.5
Bumps [ruamel-yaml]() from 0.18.3 to 0.18.5.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 14:41:55 +00:00
Willi Ballenthin
a52af3895a verbose: remove TODOs 2023-11-06 10:37:22 +00:00
Willi Ballenthin
5d31bc462b verbose: render dynamic match locations 2023-11-06 10:34:26 +00:00
Willi Ballenthin
7678897334 tests: fix render tests 2023-11-06 10:32:44 +00:00
Willi Ballenthin
75ff58edaa vverbose: better render pid/tid/call index 2023-11-06 10:09:23 +00:00
Willi Ballenthin
eb12ec43f0 mypy 2023-11-06 09:52:00 +00:00
Willi Ballenthin
f7c72cd1c3 vverbose: don't repeat rendered calls when in call scope 2023-11-06 09:52:00 +00:00
Willi Ballenthin
0da614aa4f vverbose: dynamic: show rendered matching API call 2023-11-06 09:52:00 +00:00
Willi Ballenthin
9c81ccf88a vverbose: make missing names an error 2023-11-06 09:52:00 +00:00
Willi Ballenthin
c141f7ec6e verbose: better render scopes 2023-11-06 09:52:00 +00:00
Willi Ballenthin
274a710bb1 report: better compute dynamic layout 2023-11-06 09:52:00 +00:00
Willi Ballenthin
4a7e488e4c Update capa/render/vverbose.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-11-01 12:19:13 +01:00
Willi Ballenthin
348120dea9 Merge pull request #1835 from mandiant/dependabot/pip/ruamel-yaml-0.18.3
build(deps-dev): bump ruamel-yaml from 0.17.35 to 0.18.3
2023-11-01 12:17:22 +01:00
Willi Ballenthin
435eea1b80 Merge pull request #1834 from mandiant/dependabot/pip/pytest-7.4.3
build(deps-dev): bump pytest from 7.4.2 to 7.4.3
2023-11-01 12:17:12 +01:00
Willi Ballenthin
621d42a093 Merge pull request #1831 from mandiant/dependabot/pip/flake8-no-implicit-concat-0.3.5
build(deps-dev): bump flake8-no-implicit-concat from 0.3.4 to 0.3.5
2023-11-01 12:17:04 +01:00
Willi Ballenthin
15701c6d12 Merge pull request #1829 from mandiant/dependabot/pip/mypy-1.6.1
build(deps-dev): bump mypy from 1.6.0 to 1.6.1
2023-11-01 12:16:55 +01:00
Willi Ballenthin
ec7fc86dc5 Merge pull request #1828 from mandiant/dependabot/pip/types-requests-2.31.0.10
build(deps-dev): bump types-requests from 2.31.0.2 to 2.31.0.10
2023-11-01 12:16:46 +01:00
dependabot[bot]
8d55c2f249 build(deps-dev): bump ruamel-yaml from 0.17.35 to 0.18.3
Bumps [ruamel-yaml]() from 0.17.35 to 0.18.3.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 14:11:50 +00:00
dependabot[bot]
66607f1412 build(deps-dev): bump pytest from 7.4.2 to 7.4.3
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.2 to 7.4.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.2...7.4.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 14:11:00 +00:00
Yacine
0097822e51 Merge pull request #1820 from yelhamer/capabilities-module
add a capabilities module
2023-10-27 13:39:49 +02:00
Yacine Elhamer
e559cc27d5 capa.rules: remove redundant ceng.MatchResults import 2023-10-26 19:43:26 +02:00
Yacine Elhamer
a0cec3f07d capa.rules: remove redundant is_internal_rule() and has_file_limitations() from capa source code 2023-10-26 19:41:09 +02:00
dependabot[bot]
874faf0901 build(deps-dev): bump mypy from 1.6.0 to 1.6.1
Bumps [mypy](https://github.com/python/mypy) from 1.6.0 to 1.6.1.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.6.0...v1.6.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 19:48:35 +00:00
Moritz
4750913fad Merge pull request #1827 from mandiant/dependabot/pip/black-23.10.0
build(deps-dev): bump black from 23.9.1 to 23.10.0
2023-10-24 21:47:52 +02:00
dependabot[bot]
e7198b2aaf build(deps-dev): bump flake8-no-implicit-concat from 0.3.4 to 0.3.5
Bumps [flake8-no-implicit-concat](https://github.com/10sr/flake8-no-implicit-concat) from 0.3.4 to 0.3.5.
- [Release notes](https://github.com/10sr/flake8-no-implicit-concat/releases)
- [Changelog](https://github.com/10sr/flake8-no-implicit-concat/blob/master/CHANGELOG.md)
- [Commits](https://github.com/10sr/flake8-no-implicit-concat/compare/v0.3.4...v0.3.5)

---
updated-dependencies:
- dependency-name: flake8-no-implicit-concat
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 14:47:26 +00:00
dependabot[bot]
426931c392 build(deps-dev): bump types-requests from 2.31.0.2 to 2.31.0.10
Bumps [types-requests](https://github.com/python/typeshed) from 2.31.0.2 to 2.31.0.10.
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 14:47:03 +00:00
dependabot[bot]
fec1e6a947 build(deps-dev): bump black from 23.9.1 to 23.10.0
Bumps [black](https://github.com/psf/black) from 23.9.1 to 23.10.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.9.1...23.10.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 14:46:59 +00:00
Moritz
db53424548 Merge pull request #1826 from mandiant/fix-model-hexint
fix parsing base 10/16
2023-10-23 09:02:21 +02:00
Yacine Elhamer
8029fed31c Merge branch 'capabilities-module' of https://github.com/yelhamer/capa into capabilities-module 2023-10-20 20:11:28 +02:00
Yacine Elhamer
3572b512d9 test_capabilities.py: add missing test_com_feature_matching() test 2023-10-20 20:11:08 +02:00
Yacine Elhamer
ab06c94d80 capa/main.py: move has_rule_with_namespace() to capa.rules.RuleSet 2023-10-20 20:10:29 +02:00
Willi Ballenthin
9e6919f33c layout: capture call names
so that they can be rendered to output
2023-10-20 14:21:13 +00:00
mr-tz
99042f232d fix parsing base 10/16 2023-10-20 15:26:11 +02:00
Willi Ballenthin
393b0e63f0 layout: capture process name 2023-10-20 12:39:28 +00:00
Willi Ballenthin
ee4f02908c layout: capture process name 2023-10-20 12:38:35 +00:00
Moritz
c9df78252a Ignore DLL names for API features (#1824)
* ignore DLL name for api features

* keep DLL name for import features

* fix tests
2023-10-20 13:39:15 +02:00
Willi Ballenthin
788251ba2b vverbose: render scope for humans 2023-10-20 11:37:42 +00:00
Willi Ballenthin
62d4b008c5 Merge pull request #1822 from mandiant/fix/dynamic-freeze
update freeze for dynamic
2023-10-20 13:16:48 +02:00
Capa Bot
be6f87318e Sync capa rules submodule 2023-10-20 09:50:07 +00:00
Yacine Elhamer
aae72667a3 Merge branch 'capabilities-module' of https://github.com/yelhamer/capa into capabilities-module 2023-10-20 10:16:41 +02:00
Yacine Elhamer
d6c5d98b0d move is_file_limitation_rule() to the rules module (Rule class) 2023-10-20 10:16:09 +02:00
Yacine Elhamer
d5ae2ffd91 capa.capabilities: move has_file_limitations() from capa.main to the capabilities module 2023-10-20 10:15:20 +02:00
Yacine Elhamer
96fb204d9d move capa.features.capabilities to capa.capabilities, and update scripts 2023-10-20 09:54:24 +02:00
Yacine
20604c4b41 Update capa/capabilities/static.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-10-20 09:28:13 +02:00
Yacine
423d942bd0 Update capa/capabilities/dynamic.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-10-20 09:28:05 +02:00
Yacine
f9b87417e6 Update capa/capabilities/common.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-10-20 09:27:58 +02:00
Willi Ballenthin
fc4618e234 Merge branch 'dynamic-feature-extraction' into fix/dynamic-freeze 2023-10-20 09:16:07 +02:00
Willi Ballenthin
1143f2ba56 changelog 2023-10-20 07:11:42 +00:00
Willi Ballenthin
10dc4b92b1 freeze: update freeze format v3 2023-10-20 06:59:53 +00:00
Willi Ballenthin
bfecf414fb freeze: add dynamic tests 2023-10-20 06:59:34 +00:00
Willi Ballenthin
0231ceef87 null extractor: fix typings 2023-10-20 06:59:16 +00:00
Yacine
0ae8f34aff Merge branch 'dynamic-feature-extraction' into capabilities-module 2023-10-20 08:55:49 +02:00
Moritz
b8b55f4e19 identify potential JSON object data start (#1819)
* identify potential JSON object data start
2023-10-19 17:17:57 +02:00
Willi Ballenthin
d42829d7e7 Merge pull request #1765 from mandiant/fix/dynamic-proto
protobuf: add dynamic support
2023-10-19 13:37:45 +02:00
Willi Ballenthin
c724a4b311 ci: only run BN and Ghidra tests after others complete
these are much less likely to fail because they're
changed less often, so don't run them until we know
other tests also pass.
2023-10-19 11:35:42 +00:00
Willi Ballenthin
84e22b187d doc 2023-10-19 11:29:30 +00:00
Willi Ballenthin
b6a0d6e1f3 pre-commit: fix stages 2023-10-19 11:26:22 +00:00
Willi Ballenthin
1cb3ca61cd pre-commit: only run fast checks during commit 2023-10-19 10:35:57 +00:00
Willi Ballenthin
288313a300 changelog 2023-10-19 10:28:37 +00:00
Willi Ballenthin
2cc6a37713 ci: run fast tests before the full suite 2023-10-19 10:23:03 +00:00
Willi Ballenthin
fbeb33a91f Merge branch 'dynamic-feature-extraction' into fix/dynamic-proto 2023-10-19 10:05:26 +00:00
Willi Ballenthin
3519125e03 tests: fix COM tests with dynamic scope 2023-10-19 10:04:26 +00:00
Willi Ballenthin
98360328f9 proto: fix serialization of call address 2023-10-19 09:59:18 +00:00
Willi Ballenthin
3d4facd9a3 Merge branch 'dynamic-feature-extraction' into fix/dynamic-proto 2023-10-19 09:24:37 +00:00
Willi Ballenthin
8b0ba1e656 tests: rename freeze tests 2023-10-19 09:24:18 +00:00
Willi Ballenthin
7bc3fba7b0 Merge branch 'dynamic-feature-extraction' into fix/dynamic-proto 2023-10-19 09:20:15 +00:00
Willi Ballenthin
d5e187bc70 Merge branch 'master' into dynamic-feature-extraction 2023-10-19 09:15:57 +00:00
Yacine Elhamer
85610a82c5 changelog fix 2023-10-19 10:59:45 +02:00
Yacine Elhamer
f2011c162c fix styling issues 2023-10-19 10:58:30 +02:00
Yacine Elhamer
37caeb2736 capabilities: add a test file for the new capabilities module, and move the corresponding tests from main to there 2023-10-19 10:54:53 +02:00
Yacine Elhamer
5c48f38208 capa/main.py: add a capabilities module and move all of the capability extraction there 2023-10-19 10:39:14 +02:00
Moritz
8687c740d5 Merge pull request #1817 from mandiant/improve-vv-render
improve vverbose rendering
2023-10-19 09:41:31 +02:00
Yacine
9609d63f8a Update tests/test_main.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-10-19 08:10:29 +02:00
Capa Bot
772f806eb6 Sync capa rules submodule 2023-10-18 15:01:37 +00:00
Willi Ballenthin
5eaba611d1 Merge pull request #1738 from Aayush-Goel-04/Aayush-Goel-04/Issue#322
add com class/interface features
2023-10-18 17:00:39 +02:00
mr-tz
b6f13f3489 improve vverbose rendering 2023-10-18 13:37:56 +02:00
Aayush Goel
178cfce456 Merge branch 'Aayush-Goel-04/Issue#322' of https://github.com/Aayush-Goel-04/capa into Aayush-Goel-04/Issue#322 2023-10-18 16:33:37 +05:30
Aayush Goel
94cf53a1e3 Update __init__.py 2023-10-18 16:33:31 +05:30
Moritz
2cfd45022a improve and fix various dynamic parts (#1809)
* improve and fix various dynamic parts
2023-10-18 10:59:41 +02:00
Aayush Goel
26a2d1b4d1 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#322 2023-10-17 21:09:07 +05:30
Aayush Goel
6dbd3768ce Update __init__.py 2023-10-17 21:04:21 +05:30
Willi Ballenthin
21f9e0736d isort 2023-10-17 15:07:34 +00:00
Aayush Goel
7cd5aa1c40 Added Enum for comType 2023-10-17 20:28:49 +05:30
Willi Ballenthin
55e4fddc51 mypy 2023-10-17 14:46:33 +00:00
Willi Ballenthin
1aac4a1a69 mypy 2023-10-17 14:42:58 +00:00
Willi Ballenthin
92daf3a530 elffile: fix property access 2023-10-17 14:28:52 +00:00
Willi Ballenthin
547502051f dynamic: fix tests 2023-10-17 14:27:36 +00:00
Aayush Goel
884b714be2 loading com db only once
avoid loading db multiple times by caching it.
2023-10-17 19:48:06 +05:30
Willi Ballenthin
7205bc26ef submodule: rules: update 2023-10-17 12:28:45 +00:00
Willi Ballenthin
e1b3a3f6b4 rules: fix rendering of yaml 2023-10-17 12:22:32 +00:00
Willi Ballenthin
cb5fa36fc8 flake8 2023-10-17 11:44:48 +00:00
Willi Ballenthin
8ee97acf2a dynamic: fix some tests 2023-10-17 11:43:09 +00:00
Willi Ballenthin
44d05f9498 dynamic: fix some tests 2023-10-17 11:41:40 +00:00
Willi Ballenthin
bf233c1c7a integrate Ghidra backend with dynamic analysis 2023-10-17 10:56:35 +00:00
Willi Ballenthin
182a9868ca merge master 2023-10-17 10:32:25 +00:00
Willi Ballenthin
40d9587fa4 Merge pull request #1808 from mandiant/dependabot/pip/ruamel-yaml-0.17.35
build(deps-dev): bump ruamel-yaml from 0.17.32 to 0.17.35
2023-10-17 09:59:41 +02:00
Willi Ballenthin
430fdb074b Merge pull request #1807 from mandiant/dependabot/pip/pre-commit-3.5.0
build(deps-dev): bump pre-commit from 3.4.0 to 3.5.0
2023-10-17 09:59:30 +02:00
Willi Ballenthin
0324d24490 Merge pull request #1806 from mandiant/dependabot/pip/flake8-simplify-0.21.0
build(deps-dev): bump flake8-simplify from 0.20.0 to 0.21.0
2023-10-17 09:59:21 +02:00
Willi Ballenthin
41c286d1a3 Merge pull request #1805 from mandiant/dependabot/pip/pyinstaller-6.1.0
build(deps-dev): bump pyinstaller from 6.0.0 to 6.1.0
2023-10-17 09:59:13 +02:00
Willi Ballenthin
187cf40d6f Merge pull request #1804 from mandiant/dependabot/pip/mypy-1.6.0
build(deps-dev): bump mypy from 1.5.1 to 1.6.0
2023-10-17 09:58:44 +02:00
Capa Bot
c37a0e525c Sync capa rules submodule 2023-10-16 14:53:14 +00:00
dependabot[bot]
de0c35b6ad build(deps-dev): bump ruamel-yaml from 0.17.32 to 0.17.35
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.32 to 0.17.35.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 14:18:33 +00:00
dependabot[bot]
d99b454c0e build(deps-dev): bump pre-commit from 3.4.0 to 3.5.0
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v3.4.0...v3.5.0)

---
updated-dependencies:
- dependency-name: pre-commit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 14:18:11 +00:00
dependabot[bot]
44f156925a build(deps-dev): bump flake8-simplify from 0.20.0 to 0.21.0
Bumps [flake8-simplify](https://github.com/MartinThoma/flake8-simplify) from 0.20.0 to 0.21.0.
- [Release notes](https://github.com/MartinThoma/flake8-simplify/releases)
- [Changelog](https://github.com/MartinThoma/flake8-simplify/blob/main/CHANGELOG.md)
- [Commits](https://github.com/MartinThoma/flake8-simplify/commits/0.21.0)

---
updated-dependencies:
- dependency-name: flake8-simplify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 14:17:47 +00:00
dependabot[bot]
599c115767 build(deps-dev): bump pyinstaller from 6.0.0 to 6.1.0
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 6.0.0 to 6.1.0.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v6.0.0...v6.1.0)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 14:17:36 +00:00
dependabot[bot]
6ecc9b77b9 build(deps-dev): bump mypy from 1.5.1 to 1.6.0
Bumps [mypy](https://github.com/python/mypy) from 1.5.1 to 1.6.0.
- [Commits](https://github.com/python/mypy/compare/v1.5.1...v1.6.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 14:17:01 +00:00
Aayush Goel
412d296d6b Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#322 2023-10-16 16:38:18 +05:30
Aayush Goel
db32d90480 tests updated 2023-10-16 16:35:30 +05:30
Yacine Elhamer
9a66c265db cape/file.py: fix flake8 issue of using '+' for logging 2023-10-16 12:11:07 +02:00
Yacine Elhamer
a1aca3aeb3 Merge branch 'dynamic-feature-extraction' of https://github.com/mandiant/capa into dynamic-feature-extraction 2023-10-16 12:04:47 +02:00
Yacine Elhamer
ffe6ab6842 main.py: load signatures only for the static context 2023-10-16 12:04:38 +02:00
Yacine
d1b7afbe13 Update capa/render/verbose.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-10-14 09:36:55 +02:00
Capa Bot
77de088ac9 Sync capa rules submodule 2023-10-12 09:01:30 +00:00
Capa Bot
40ba6679f0 Sync capa-testfiles submodule 2023-10-11 14:36:05 +00:00
Moritz
8b6fa35e9f Merge pull request #1794 from mandiant/dependabot/pip/pyinstaller-6.0.0
build(deps-dev): bump pyinstaller from 5.10.1 to 6.0.0
2023-10-11 13:58:48 +02:00
Moritz
f85ea915bf Update pyinstaller.spec 2023-10-11 12:29:18 +02:00
Moritz
312ad48041 Merge pull request #1801 from mandiant/dependabot/pip/dnfile-0.14.1
build(deps-dev): bump dnfile from 0.13.0 to 0.14.1
2023-10-11 12:20:07 +02:00
Moritz
65b80d4d13 Merge pull request #1800 from mandiant/dependabot/pip/flake8-bugbear-23.9.16
build(deps-dev): bump flake8-bugbear from 23.7.10 to 23.9.16
2023-10-11 12:19:51 +02:00
Moritz
fb098fde5f Merge pull request #1799 from mandiant/dependabot/pip/black-23.9.1
build(deps-dev): bump black from 23.7.0 to 23.9.1
2023-10-11 12:19:36 +02:00
Moritz
eedec933c2 Merge pull request #1798 from mandiant/dependabot/pip/wcwidth-0.2.8
build(deps-dev): bump wcwidth from 0.2.6 to 0.2.8
2023-10-11 12:19:20 +02:00
Yacine Elhamer
559f2fd162 cape/file.py: flake8 fixes 2023-10-11 11:56:49 +02:00
Yacine Elhamer
953b2e82d2 rendering: several fixes and added types/classes 2023-10-11 11:52:16 +02:00
Capa Bot
cd268d6327 Sync capa rules submodule 2023-10-10 13:34:52 +00:00
Aayush Goel
23ecb248a5 Update __init__.py 2023-10-10 18:08:07 +05:30
Aayush Goel
bc165331db Update __init__.py 2023-10-10 17:56:18 +05:30
Capa Bot
5d66a389d3 Sync capa rules submodule 2023-10-10 10:09:36 +00:00
Capa Bot
248a51c15f Sync capa rules submodule 2023-10-10 09:55:31 +00:00
Aayush Goel
8a0628f357 Update CHANGELOG.md 2023-10-10 04:16:38 +05:30
Aayush Goel
2ec87f717a Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#322 2023-10-10 04:06:28 +05:30
Capa Bot
4430fce314 Sync capa rules submodule 2023-10-09 18:13:48 +00:00
Capa Bot
174c8121ca Sync capa rules submodule 2023-10-09 18:01:23 +00:00
Capa Bot
fa1371cfa8 Sync capa rules submodule 2023-10-09 18:00:29 +00:00
Capa Bot
a0a2b07b85 Sync capa rules submodule 2023-10-09 16:35:56 +00:00
Moritz
a9daa92c9a Merge branch 'master' into Aayush-Goel-04/Issue#322 2023-10-09 18:22:46 +02:00
Capa Bot
b315aacd73 Sync capa rules submodule 2023-10-09 16:22:26 +00:00
Capa Bot
3dd051582a Sync capa rules submodule 2023-10-09 16:01:44 +00:00
Capa Bot
5f7b4fbf74 Sync capa rules submodule 2023-10-06 15:20:18 +00:00
Yacine Elhamer
8b287c1704 scripts/profile_time.py: revert restriction that sample extractors can only be static ones 2023-10-04 10:51:53 +02:00
Yacine Elhamer
28a722d4c3 scripts/profile_time.py: revert restriction that frozen extractors can only be static ones 2023-10-04 10:51:02 +02:00
Yacine Elhamer
35f64f37bb cape/global_.py: throw exceptions for unrecognized OSes, formats, and architectures 2023-10-04 10:36:08 +02:00
Yacine Elhamer
7d9ae57692 check for pid and ppid reuse 2023-10-04 10:28:10 +02:00
Mike Hunhoff
b1175ab16a adding capa quickstart reference (#1802) 2023-10-03 12:05:55 -06:00
dependabot[bot]
838205b375 build(deps-dev): bump dnfile from 0.13.0 to 0.14.1
Bumps [dnfile](https://github.com/malwarefrank/dnfile) from 0.13.0 to 0.14.1.
- [Changelog](https://github.com/malwarefrank/dnfile/blob/master/HISTORY.rst)
- [Commits](https://github.com/malwarefrank/dnfile/compare/v0.13.0...v0.14.1)

---
updated-dependencies:
- dependency-name: dnfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 14:42:47 +00:00
dependabot[bot]
0fbec49708 build(deps-dev): bump flake8-bugbear from 23.7.10 to 23.9.16
Bumps [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) from 23.7.10 to 23.9.16.
- [Release notes](https://github.com/PyCQA/flake8-bugbear/releases)
- [Commits](https://github.com/PyCQA/flake8-bugbear/compare/23.7.10...23.9.16)

---
updated-dependencies:
- dependency-name: flake8-bugbear
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 14:42:40 +00:00
dependabot[bot]
0bdc727dce build(deps-dev): bump black from 23.7.0 to 23.9.1
Bumps [black](https://github.com/psf/black) from 23.7.0 to 23.9.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.7.0...23.9.1)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 14:42:28 +00:00
dependabot[bot]
8ea7708a38 build(deps-dev): bump wcwidth from 0.2.6 to 0.2.8
Bumps [wcwidth](https://github.com/jquast/wcwidth) from 0.2.6 to 0.2.8.
- [Release notes](https://github.com/jquast/wcwidth/releases)
- [Commits](https://github.com/jquast/wcwidth/compare/0.2.6...0.2.8)

---
updated-dependencies:
- dependency-name: wcwidth
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 14:42:16 +00:00
Capa Bot
9b5c906c2a Sync capa rules submodule 2023-09-27 20:40:53 +00:00
Willi Ballenthin
240376153a Merge pull request #1791 from xusheng6/test_binja_forwarded_export
binja: add support for forwarded exports
2023-09-27 11:35:00 +02:00
Willi Ballenthin
321ef100c5 Update capa/features/extractors/binja/helpers.py 2023-09-27 08:56:42 +02:00
Willi Ballenthin
d8eebf524e Update capa/features/extractors/binja/helpers.py 2023-09-27 08:51:12 +02:00
dependabot[bot]
c6c54c316f build(deps-dev): bump pyinstaller from 5.10.1 to 6.0.0
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 5.10.1 to 6.0.0.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v5.10.1...v6.0.0)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-27 06:50:58 +00:00
Willi Ballenthin
b1e00150f4 Merge pull request #1783 from mandiant/dependabot/pip/pytest-7.4.2
build(deps-dev): bump pytest from 7.4.0 to 7.4.2
2023-09-27 08:50:24 +02:00
Willi Ballenthin
83a7ce0b82 Merge pull request #1784 from mandiant/dependabot/pip/build-1.0.3
build(deps-dev): bump build from 0.10.0 to 1.0.3
2023-09-27 08:49:54 +02:00
Willi Ballenthin
303170f45d Merge pull request #1785 from mandiant/dependabot/pip/pyelftools-0.30
build(deps-dev): bump pyelftools from 0.29 to 0.30
2023-09-27 08:48:59 +02:00
Willi Ballenthin
8a019aa360 Merge branch 'master' into test_binja_forwarded_export 2023-09-27 08:48:21 +02:00
Willi Ballenthin
3dffa8145f Update capa/features/extractors/binja/helpers.py 2023-09-27 08:47:52 +02:00
Willi Ballenthin
782a5b3aa7 Merge pull request #1793 from mandiant/dependabot/pip/ruff-0.0.291
build(deps-dev): bump ruff from 0.0.290 to 0.0.291
2023-09-25 20:26:02 +02:00
dependabot[bot]
b0af78569c build(deps-dev): bump ruff from 0.0.290 to 0.0.291
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.290 to 0.0.291.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.290...v0.0.291)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-25 14:16:40 +00:00
Capa Bot
79cef0e783 Sync capa-testfiles submodule 2023-09-22 10:33:01 +00:00
Willi Ballenthin
09b54a86f0 Merge branch 'master' into test_binja_forwarded_export 2023-09-21 12:10:13 +02:00
Willi Ballenthin
57106701c4 Merge pull request #1792 from xusheng6/binja_symtab
binja: add support for symtab names. Fix #1504
2023-09-21 12:06:13 +02:00
Xusheng
55af6f052f binja: add support for symtab names. Fix #1504 2023-09-21 17:24:42 +08:00
Xusheng
d2d32f88ef binja: add support for forwarded exports 2023-09-21 15:32:55 +08:00
Willi Ballenthin
7abcf3de9a Merge pull request #1790 from xusheng6/test_update_bn_35 2023-09-21 07:13:51 +02:00
Xusheng
b3dccb3841 binja: improve function call site detection 2023-09-21 09:51:01 +08:00
Xusheng
bc71c94171 binja: use binaryninja.load to open a binary 2023-09-21 09:51:01 +08:00
Xusheng
59d03b3ba3 binja: bump Binary Ninja version to 3.5 2023-09-20 21:00:04 +08:00
Willi Ballenthin
3a5c8ec3b8 Merge pull request #1788 from mandiant/dependabot/pip/ruff-0.0.290
build(deps-dev): bump ruff from 0.0.286 to 0.0.290
2023-09-19 14:17:33 +02:00
dependabot[bot]
fd3678904a build(deps-dev): bump ruff from 0.0.286 to 0.0.290
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.286 to 0.0.290.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.286...v0.0.290)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-18 14:36:44 +00:00
Capa Bot
d04ae5294e Sync capa-testfiles submodule 2023-09-13 14:50:29 +00:00
Capa Bot
6bae9d757d Sync capa rules submodule 2023-09-13 14:46:47 +00:00
dependabot[bot]
b9c05cf44a build(deps-dev): bump pyelftools from 0.29 to 0.30
Bumps [pyelftools](https://github.com/eliben/pyelftools) from 0.29 to 0.30.
- [Changelog](https://github.com/eliben/pyelftools/blob/master/CHANGES)
- [Commits](https://github.com/eliben/pyelftools/compare/v0.29...v0.30)

---
updated-dependencies:
- dependency-name: pyelftools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-11 14:14:27 +00:00
dependabot[bot]
dc32289aab build(deps-dev): bump build from 0.10.0 to 1.0.3
Bumps [build](https://github.com/pypa/build) from 0.10.0 to 1.0.3.
- [Release notes](https://github.com/pypa/build/releases)
- [Changelog](https://github.com/pypa/build/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/build/compare/0.10.0...1.0.3)

---
updated-dependencies:
- dependency-name: build
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-11 14:14:20 +00:00
dependabot[bot]
3c1a8f4461 build(deps-dev): bump pytest from 7.4.0 to 7.4.2
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.0 to 7.4.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.0...7.4.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-11 14:14:11 +00:00
Aayush Goel
8331ed6ea0 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#322 2023-09-06 16:35:29 +05:30
Mike Hunhoff
b0d55143a4 ghidra: update CI to use /Ghidra/Extensions (#1782) 2023-09-05 13:21:52 -06:00
Capa Bot
e006702245 Sync capa rules submodule 2023-09-05 13:02:13 +00:00
Willi Ballenthin
72e836166f proto: better convert to/from proto 2023-09-05 10:24:53 +00:00
Willi Ballenthin
d64ab41dfd tests: proto: add more dynamic proto tests 2023-09-05 10:23:55 +00:00
Willi Ballenthin
5b4c167489 proto: add additional types 2023-09-05 10:23:30 +00:00
Willi Ballenthin
2a757b0cbb submodule: test data: update 2023-09-05 10:22:59 +00:00
Willi Ballenthin
69836a0f13 proto: add dynamic test 2023-09-05 10:22:33 +00:00
Willi Ballenthin
866c7c5ce4 proto: deprecate metadata.analysis 2023-09-05 08:39:37 +00:00
Willi Ballenthin
3725618d50 render: proto: use Static/Dynamic analysis types 2023-09-05 08:37:11 +00:00
Willi Ballenthin
766b05e5c3 Merge branch 'dynamic-feature-extraction' into fix/dynamic-proto 2023-09-05 08:18:51 +00:00
Willi Ballenthin
1224b7e514 Merge pull request #1776 from mandiant/dependabot/pip/pre-commit-3.4.0
build(deps-dev): bump pre-commit from 3.3.3 to 3.4.0
2023-09-04 21:45:08 +02:00
dependabot[bot]
46e3ed1100 build(deps-dev): bump pre-commit from 3.3.3 to 3.4.0
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.3.3 to 3.4.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v3.3.3...v3.4.0)

---
updated-dependencies:
- dependency-name: pre-commit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 14:45:22 +00:00
Yacine Elhamer
dd0eadb438 freeze/__init__.py: bump freeze version to 3 2023-09-04 11:51:22 +02:00
Yacine Elhamer
f905ed611b Merge branch 'dynamic-feature-extraction' of https://github.com/mandiant/capa into dynamic-feature-extraction 2023-09-04 11:04:38 +02:00
Yacine Elhamer
cfa703eaae remove type comment 2023-09-04 11:04:09 +02:00
Yacine Elhamer
9ec1bf3e42 point rules towards dynamic-syntax 2023-09-04 10:38:01 +02:00
Yacine Elhamer
d83c0e70de main.py: remove comment type annotations 2023-09-04 09:59:29 +02:00
Yacine Elhamer
1d8e650d7b freeze/__init__.py: bump freeze version to 3 2023-09-04 09:50:29 +02:00
Yacine
99caa87a3d Update capa/main.py
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-09-04 09:46:41 +02:00
Mike Hunhoff
7b08f2d55a Merge pull request #1770 from mandiant/backend-ghidra
ghidra: add Ghidra feature extractor and supporting code
2023-08-30 10:41:01 -06:00
Mike Hunhoff
d17db614b9 Update README.md 2023-08-30 10:33:38 -06:00
Aayush Goel
6317153ef0 Update tests/test_rules.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-08-30 21:48:55 +05:30
Aayush Goel
24dad6bcc4 Update capa/rules/__init__.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-08-30 21:48:48 +05:30
Yacine Elhamer
73c158ad68 point submodules towards the right branch 2023-08-30 11:42:43 +02:00
Yacine Elhamer
47330e69d4 verbose.py render_dynamic_meta(): s/doc: rd.ResultDocument/meta: rd.MetaData/g 2023-08-29 22:42:18 +02:00
Yacine Elhamer
0987673bf3 verbose.py: temporarily add a mypy-related assert to render_static_meta() 2023-08-29 22:38:14 +02:00
Yacine Elhamer
2c75f786c3 main.py rdoc.Metadata creation: revert to usage of as_posix() within the call to rdoc.Sample() 2023-08-29 22:35:49 +02:00
Yacine Elhamer
09afcfbac1 render/verbose.py: remove frz.AddressType.FREEZE 2023-08-29 22:31:16 +02:00
Aayush Goel
ab3747e448 added com prefix CLSID, IID 2023-08-30 01:00:07 +05:30
colton-gabertan
72ed4d1165 push shellcode example 2023-08-29 18:05:03 +00:00
colton-gabertan
0ec682a464 add shellcode documentation & update Headless Analyzer example 2023-08-29 18:01:11 +00:00
colton-gabertan
37917b6181 update ghidra feat extractor docs 2023-08-29 17:28:49 +00:00
Mike Hunhoff
a6e61ed6f1 Update capa/ghidra/README.md
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-08-29 09:03:26 -06:00
Mike Hunhoff
1fddf800c6 Update capa/ghidra/README.md
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-08-29 09:02:46 -06:00
Mike Hunhoff
0ffd631606 Update .github/workflows/tests.yml
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-08-29 09:00:14 -06:00
Mike Hunhoff
7cc10401d5 fix #1772 2023-08-28 15:15:47 -06:00
Mike Hunhoff
3929164fc2 Merge branch 'backend-ghidra' of github.com:mandiant/capa into backend-ghidra 2023-08-28 13:24:23 -06:00
Mike Hunhoff
f3a2a5958d fix Ghidra detection 2023-08-28 13:24:14 -06:00
Colton Gabertan
6d3f649a0c remove backend-ghidra from CI 2023-08-28 12:21:30 -07:00
Colton Gabertan
e00608e298 ghidra hotfix: fix ghidrathon download (#1771)
* hotfix: fix ghidrathon download
2023-08-28 12:19:45 -07:00
Mike Hunhoff
995014afc2 merge upstream 2023-08-28 12:40:49 -06:00
Mike Hunhoff
a522ae20f1 update CHANGELOG 2023-08-28 12:40:02 -06:00
Mike Hunhoff
203fc36865 cleanup CHANGELOG merge 2023-08-28 12:33:07 -06:00
Mike Hunhoff
7bd2467074 remove backend-ghidra from workflows 2023-08-28 12:32:52 -06:00
Willi Ballenthin
f339bbf68c Merge pull request #1769 from mandiant/dependabot/pip/ruff-0.0.286
build(deps-dev): bump ruff from 0.0.285 to 0.0.286
2023-08-28 20:26:11 +02:00
Mike Hunhoff
8ed4062cf1 sync rules submodule with upstream 2023-08-28 12:13:10 -06:00
dependabot[bot]
807792f879 build(deps-dev): bump ruff from 0.0.285 to 0.0.286
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.285 to 0.0.286.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.285...v0.0.286)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-28 14:48:55 +00:00
Yacine
9dc457e61e Update capa/features/freeze/__init__.py
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-08-28 15:40:31 +02:00
Yacine Elhamer
9eb88e6ca7 Merge branch 'dynamic-feature-extraction' of https://github.com/mandiant/capa into dynamic-feature-extraction 2023-08-28 13:24:58 +02:00
Yacine Elhamer
214a355b9c binja extractor: remove unused pathlib.Path import 2023-08-28 13:24:54 +02:00
Colton Gabertan
9cea7346b2 ghidra: documentation (#1759)
* Implement ghidra documentation
2023-08-27 19:21:36 -07:00
Yacine
4d538b939e Update scripts/import-to-ida.py
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-08-27 14:59:10 +02:00
Yacine Elhamer
8c9e676868 binja: use binja api's methods to get the file hash 2023-08-27 14:31:43 +02:00
Yacine Elhamer
b0133f0aa1 various fixes 2023-08-26 19:28:07 +02:00
Yacine Elhamer
49adecb25c add yaml representer for the Scope class, as well as other bugfixes 2023-08-26 18:11:35 +02:00
Yacine Elhamer
e9a9b3a6b6 point the data file to the latest PR 2023-08-26 13:04:45 +02:00
colton-gabertan
d7c9ae26bc Merge branch 'master' into backend-ghidra 2023-08-26 02:08:22 +00:00
Colton Gabertan
fddec33d04 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__
2023-08-25 19:03:38 -07:00
Mike Hunhoff
65179805a7 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
2023-08-25 18:35:59 -07:00
Yacine
d5daa79547 Merge pull request #1764 from mandiant/fix/scope-enum-usage
rules: use Scope enum instead of constants
2023-08-25 20:58:34 +03:00
Aayush Goel
90df85b332 test for com_feature
matching a file as expected
generating the bytes/strings
if an unknown COM class/interface is provided?
2023-08-25 20:59:58 +05:30
Willi Ballenthin
88ee6e661e wip: proto: add Metadata.[static, dynamic]_analysis 2023-08-25 14:40:50 +00:00
Willi Ballenthin
08c9bbcc91 proto: deprecate RuleMetadata.scope 2023-08-25 13:22:48 +00:00
Willi Ballenthin
f96b9e6a6e proto: add RuleMetadata.scopes 2023-08-25 13:20:46 +00:00
Willi Ballenthin
9bbd3184b0 rules: handle unsupported scopes again 2023-08-25 13:15:55 +00:00
Willi Ballenthin
e4c1361d42 Merge branch 'fix/scope-enum-usage' into fix/dynamic-proto 2023-08-25 13:01:49 +00:00
Willi Ballenthin
17e4765728 changelog 2023-08-25 13:00:34 +00:00
Willi Ballenthin
7e258a91ec Merge branch 'dynamic-feature-extraction' into fix/scope-enum-usage 2023-08-25 14:59:18 +02:00
Willi Ballenthin
b88853f327 changelog 2023-08-25 14:59:03 +02:00
Willi Ballenthin
a60401fc7e Merge branch 'master' into dynamic-feature-extraction 2023-08-25 14:58:35 +02:00
Willi Ballenthin
a734358377 rules: use Scope enum instead of constants 2023-08-25 12:54:57 +00:00
Willi Ballenthin
ebcbad3ae3 proto: add new scopes 2023-08-25 12:21:37 +00:00
Willi Ballenthin
8ff74d4a04 proto: regenerate using 3.21 protoc 2023-08-25 12:20:51 +00:00
Aayush Goel
bd0d8eb403 Update __init__.py
added parse_description for com feature
Update CHANGELOG.md
added comments, dealt with errors
2023-08-25 16:04:25 +05:30
Aayush Goel
9b79aa1983 Merge branch 'Aayush-Goel-04/Issue#322' of https://github.com/Aayush-Goel-04/capa into Aayush-Goel-04/Issue#322 2023-08-25 15:42:17 +05:30
Aayush Goel
172968c77e Update CHANGELOG.md 2023-08-25 15:42:02 +05:30
Aayush Goel
f1a7049ab5 Merge branch 'master' into Aayush-Goel-04/Issue#322 2023-08-25 15:39:03 +05:30
Aayush Goel
155a2904fb Update CHANGELOG.md 2023-08-25 15:38:00 +05:30
Aayush Goel
4c2e8fd718 Merge branch 'Aayush-Goel-04/Issue#322' of https://github.com/Aayush-Goel-04/capa into Aayush-Goel-04/Issue#322 2023-08-25 15:33:52 +05:30
Aayush Goel
95e279a03b update com db
moved code to rules/init.py , create db for coms
2023-08-25 15:32:40 +05:30
Willi Ballenthin
f2909c82f3 proto: reenable tests and linters 2023-08-25 09:41:25 +00:00
Willi Ballenthin
164b08276c extractor: tweak hashes to fix mypy 2023-08-25 09:38:23 +00:00
Willi Ballenthin
b930523d44 freeze: add TODO issue link 2023-08-25 11:32:56 +02:00
Willi Ballenthin
9d21addc6b Merge pull request #1763 from mandiant/v6.1.0
version: v6.1.0
2023-08-25 11:11:59 +02:00
Willi Ballenthin
9accb60eff changelog 2023-08-25 09:11:04 +00:00
Willi Ballenthin
61202913a6 changelog 2023-08-25 09:07:09 +00:00
Willi Ballenthin
2b59fef1b2 changelog 2023-08-25 09:05:57 +00:00
Willi Ballenthin
ddff8634de changelog 2023-08-25 09:04:26 +00:00
Willi Ballenthin
1905f1bfbd changelog 2023-08-25 09:02:03 +00:00
Yacine Elhamer
f34b0355e7 test_result_document.py: re-enable result-document related tests 2023-08-25 10:56:12 +02:00
Willi Ballenthin
7a70bc9b2a version: v6.1.0 2023-08-25 08:47:11 +00:00
Yacine
3ee56e3bee Merge pull request #1762 from yelhamer/modify-sample-hashes
Modify sample hashes
2023-08-25 10:29:38 +03:00
Yacine Elhamer
49bf2eb6d4 base_extractor.py: replace dunder with single underscore for sample_hashes attribute 2023-08-25 10:14:25 +02:00
Yacine Elhamer
707dee4c3f base_Extractor.py: make sample_hashes attribute private 2023-08-25 09:53:08 +02:00
Yacine Elhamer
0ded827290 modify null extractor 2023-08-25 08:50:34 +02:00
Yacine Elhamer
f74107d960 initial commit 2023-08-25 08:37:57 +02:00
Mike Hunhoff
448b122ef0 fix ints_to_bytes performance (#1761)
* fix ints_to_bytes performance
2023-08-24 16:01:41 -07:00
colton-gabertan
bd2f7bc1f4 hotfix: fix indirect address dereference handling 2023-08-24 22:09:08 +00:00
Yacine
acd3a30d27 Merge pull request #1758 from yelhamer/fix-cape2fmt
Add dynamic scopes to capa2fmt
2023-08-24 15:43:34 +03:00
Yacine Elhamer
b636f23e3c Merge branch 'fix-cape2fmt' of https://github.com/yelhamer/capa into fix-cape2fmt 2023-08-24 15:01:00 +02:00
Yacine Elhamer
70eae1a6f0 freeze/__init__.py: fix missing space 2023-08-24 15:00:34 +02:00
Yacine Elhamer
3574bd49bd Merge remote-tracking branch 'parentrepo/dynamic-feature-extraction' into fix-cape2fmt 2023-08-24 14:48:07 +02:00
Yacine Elhamer
46217a3acb test_main.py: remove unused pytest 2023-08-24 14:47:40 +02:00
Yacine Elhamer
9eb1255b29 cape2yara.py: update for use of scopes, and fix bug 2023-08-24 14:32:49 +02:00
Yacine
d66f834e54 Update tests/test_scripts.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-08-24 13:48:32 +02:00
Yacine Elhamer
7c101f01e5 test_binja.py: revert ruleset-related xfails 2023-08-24 13:36:53 +02:00
Yacine Elhamer
42689ef1da test_main.py: revert ruleset-related xfails 2023-08-24 13:30:22 +02:00
Colton Gabertan
70d36ab640 properly set bounds for find_byte_sequence (#1757) 2023-08-23 15:40:15 -06:00
Colton Gabertan
19b8000c00 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
2023-08-23 14:35:18 -06:00
colton-gabertan
06f48063d0 Merge branch 'master' into backend-ghidra 2023-08-23 18:05:58 +00:00
Yacine
5ba7325646 Merge pull request #1753 from yelhamer/update-linter
Update the rules linter
2023-08-23 11:50:51 +03:00
Yacine
86effec1a2 capa/rules/__init__.py: merge features from small scopes into larger ones
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-08-23 08:49:36 +03:00
Yacine
cdb469eca0 capa/features/freeze/__init__.py: remove comment
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-08-23 08:45:21 +03:00
Yacine
39c8fd8286 Update capa/features/freeze/__init__.py
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-08-23 08:43:36 +03:00
Yacine Elhamer
5730e5515f lint.py: update recommendation messages 2023-08-23 01:42:22 +02:00
Yacine Elhamer
901ba551bc lint.py: fix boolean statement 2023-08-23 01:41:44 +02:00
Yacine Elhamer
77b3fadf79 lint.py: add 'unsupported' keyword 2023-08-23 01:39:14 +02:00
Yacine Elhamer
44fc3357d1 initial commit 2023-08-23 01:32:01 +02:00
Willi Ballenthin
25414044ef Merge pull request #1748 from mandiant/feat/issue-1744
rules: add scope terms "unsupported" and "unspecified"
2023-08-22 15:59:57 +02:00
Yacine Elhamer
d1068991e3 test_rules_insn_scope.py: update rules missing the dynamic scope 2023-08-22 16:26:54 +02:00
Willi Ballenthin
4ab240e990 rules: add scope terms "unsupported" and "unspecified"
closes #1744
2023-08-22 12:58:06 +00:00
Willi Ballenthin
9489927bed Merge pull request #1746 from mandiant/fix/issue-1745
fix detection of CAPE reports
2023-08-22 14:34:23 +02:00
Willi Ballenthin
c160f45849 main: fix rendering of logging message 2023-08-22 12:32:53 +00:00
Willi Ballenthin
5b585c0e39 cape: better detect CAPE reports
fixes #1745
2023-08-22 12:32:30 +00:00
Aayush Goel
c6ee919619 Update capa/features/common.py
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-08-22 15:52:04 +05:30
Willi Ballenthin
675ad364ac point submodule rules to branch dynamic-syntax 2023-08-22 08:50:18 +00:00
Willi Ballenthin
21cefa0932 Merge branch 'master' into dynamic-feature-extraction 2023-08-22 09:53:42 +02:00
Willi Ballenthin
934d0f969b Merge pull request #1740 from mandiant/dependabot/pip/mypy-1.5.1
build(deps-dev): bump mypy from 1.5.0 to 1.5.1
2023-08-22 09:53:15 +02:00
dependabot[bot]
b7b79b565b build(deps-dev): bump mypy from 1.5.0 to 1.5.1
Bumps [mypy](https://github.com/python/mypy) from 1.5.0 to 1.5.1.
- [Commits](https://github.com/python/mypy/compare/v1.5.0...v1.5.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-22 07:48:33 +00:00
Moritz
979aab3098 Merge pull request #1741 from mandiant/dependabot/pip/ruff-0.0.285
build(deps-dev): bump ruff from 0.0.284 to 0.0.285
2023-08-22 09:47:50 +02:00
Willi Ballenthin
89c8c6d212 Update capa/rules/__init__.py 2023-08-22 09:38:41 +02:00
Willi Ballenthin
e5af7165ea Update capa/features/freeze/__init__.py 2023-08-22 09:31:35 +02:00
Willi Ballenthin
ee936f9257 Merge pull request #1729 from mandiant/feat/cape-pydantic
add Pydantic models for CAPE sandbox
2023-08-22 09:25:02 +02:00
Colton Gabertan
058c1fefd2 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
2023-08-21 12:16:13 -06:00
dependabot[bot]
8ed00a2847 build(deps-dev): bump ruff from 0.0.284 to 0.0.285
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.284 to 0.0.285.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.284...v0.0.285)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 14:50:50 +00:00
Aayush Goel
6482848fa4 Merge branch 'Aayush-Goel-04/Issue#322' of https://github.com/Aayush-Goel-04/capa into Aayush-Goel-04/Issue#322 2023-08-20 00:39:50 +05:30
Aayush Goel
7c2a736c4b Update CHANGELOG.md 2023-08-20 00:38:35 +05:30
Aayush Goel
918ec22667 Merge branch 'master' into Aayush-Goel-04/Issue#322 2023-08-20 00:38:26 +05:30
Aayush Goel
1027da9be0 add new feature for com 2023-08-20 00:36:37 +05:30
Capa Bot
5787e41dd2 Sync capa rules submodule 2023-08-19 18:14:15 +00:00
Capa Bot
0265657937 Sync capa rules submodule 2023-08-19 09:36:35 +00:00
Capa Bot
73477b6495 Sync capa rules submodule 2023-08-19 09:34:30 +00:00
Yacine Elhamer
521bd25d31 remove file-limitations checks for dynamic extractors 2023-08-18 15:23:19 +02:00
Yacine Elhamer
e7c0bea6e5 Match.from_capa(): remove reliance on the meta field to get the scope 2023-08-18 15:05:15 +02:00
Yacine Elhamer
a8bd5b1119 disable packed-sample warning for dynamic feature extractors 2023-08-18 14:31:32 +02:00
Yacine Elhamer
9144d12e51 add error message for invalid report files 2023-08-18 14:28:02 +02:00
Yacine Elhamer
d741544514 result_document.py: use the scopes attribute instead of meta["scope"] 2023-08-18 14:15:36 +02:00
Willi Ballenthin
5e31f0df23 cape: models: more fixes thanks to avast 2023-08-18 10:19:07 +00:00
Willi Ballenthin
18dff9d664 cape: models: more fixes thanks to avast 2023-08-18 10:15:12 +00:00
Yacine Elhamer
350094759a main.py: look up rules scope with scopes attribute, not their meta field 2023-08-18 12:37:42 +02:00
Willi Ballenthin
b10275e851 black 2023-08-18 08:23:21 +00:00
Willi Ballenthin
05cf7201ad Merge branch 'dynamic-feature-extraction' into feat/cape-pydantic 2023-08-18 10:22:55 +02:00
Willi Ballenthin
8cd5e03e87 ci: pre-commit: show-diff-on-failure 2023-08-18 08:19:27 +00:00
Willi Ballenthin
120917e0b5 cape: models: tweaks from Avast dataset 2023-08-18 08:10:55 +00:00
colton-gabertan
a2a2949675 Merge branch 'master' into backend-ghidra 2023-08-17 16:06:17 +00:00
Colton Gabertan
b3cf1129e3 Ghidra: Implement GhidraFeatureExtractor (#1681)
* Implement GhidraFeatureExtractor & repo changes
2023-08-16 15:58:47 -07:00
Yacine
264958ebfe Update capa/features/common.py
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-08-16 16:12:26 +02:00
Willi Ballenthin
3614ce1409 cape: fix test failures 2023-08-16 11:43:45 +00:00
Willi Ballenthin
c80542ded3 cape: call: fix argument type switch 2023-08-16 11:37:41 +00:00
Willi Ballenthin
3350a936b7 ida: use ida_nalt not idaapi
closes #1730
2023-08-16 13:33:01 +02:00
Willi Ballenthin
724db83920 cape: require PE analysis 2023-08-16 13:23:00 +02:00
Willi Ballenthin
8788a40d12 Merge branch 'dynamic-feature-extraction' into feat/cape-pydantic 2023-08-16 13:13:29 +02:00
Willi Ballenthin
6f7bf96776 cape: use pydantic model 2023-08-16 11:12:05 +00:00
Willi Ballenthin
e943a71dff cape: models: relax deserializing FlexibleModels 2023-08-16 10:04:20 +00:00
Willi Ballenthin
4be1c89c5b cape: models: more data shapes 2023-08-16 09:50:13 +00:00
Willi Ballenthin
2eda053c79 cape: models: more data shapes 2023-08-16 09:41:36 +00:00
Willi Ballenthin
26539e68d9 cape: models: add tests 2023-08-16 08:57:54 +00:00
Willi Ballenthin
046427cf55 cape: model: document the data we'll use in cape 2023-08-16 08:57:17 +00:00
Willi Ballenthin
25aabcd7e4 cape: models: more shapes 2023-08-16 07:48:59 +00:00
Willi Ballenthin
d8bea816dd cape: models: add more fields 2023-08-15 14:36:49 +00:00
Willi Ballenthin
bb2b1824a9 Merge branch 'master' into dynamic-feature-extraction 2023-08-15 14:01:30 +02:00
Willi Ballenthin
7e78133925 Merge pull request #1728 from mandiant/fix/issue-1719
fix deprecation warnings
2023-08-15 14:00:15 +02:00
Willi Ballenthin
59a129d6d6 cape: add pydantic model for v2.2 2023-08-15 11:54:15 +00:00
Willi Ballenthin
db40d9bc7a wip: add initial CAPE model 2023-08-15 11:41:11 +00:00
Yacine
d71ecc7a79 Update tests/test_ida_features.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-08-15 12:26:19 +02:00
Yacine
a5a1a0bfee Update CHANGELOG.md
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-08-15 12:26:02 +02:00
Willi Ballenthin
827b4b29b4 test_rules: fix rule scoping logic 2023-08-15 09:21:49 +00:00
Willi Ballenthin
2a31b16567 merge 2023-08-15 08:56:41 +00:00
Willi Ballenthin
8118a3f353 changelog 2023-08-15 08:46:18 +00:00
Willi Ballenthin
e6d64ef561 pydantic: remove use of deprecated routines
closes #1718
2023-08-15 08:41:56 +00:00
Willi Ballenthin
408c5076c6 tests: ida: don't collect tests as pytest tests
closes #1719
2023-08-15 08:26:59 +00:00
Willi Ballenthin
c001c883f7 Merge pull request #1714 from mandiant/fix/issue-1697-1
rule scoping tweaks
2023-08-15 10:16:01 +02:00
Willi Ballenthin
476c7ff749 main: provide encoding to open
fixes flake8 warning
2023-08-15 08:13:22 +00:00
Willi Ballenthin
4978aa74e7 tests: temporarily xfail script test
closes #1717
2023-08-15 08:13:14 +00:00
Yacine Elhamer
4411911664 Merge remote-tracking branch 'parentrepo/dynamic-feature-extraction' into fix/issue-1697-1 2023-08-15 09:57:13 +02:00
Yacine
0e1ce21488 Merge pull request #1715 from mandiant/fix/issue-1710
fix rendering of scope in vverbose mode
2023-08-15 09:51:53 +02:00
Yacine
88aa17fa7b Merge pull request #1716 from mandiant/fix/issue-1697-2
remove dynamic return address concept
2023-08-15 08:55:12 +02:00
Willi Ballenthin
3169ee28e9 Merge pull request #1721 from mandiant/fix/issue-1704
elf: fix parsing of symtab from viv data
2023-08-14 17:13:50 +02:00
Willi Ballenthin
d648fdf6c0 Merge pull request #1713 from mandiant/fix/issue-1711
record and show the analysis flavor
2023-08-14 16:44:42 +02:00
Willi Ballenthin
3b9f5114ce Merge pull request #1722 from mandiant/dependabot/pip/mypy-1.5.0
build(deps-dev): bump mypy from 1.4.1 to 1.5.0
2023-08-14 16:43:57 +02:00
dependabot[bot]
623fc270c1 build(deps-dev): bump mypy from 1.4.1 to 1.5.0
Bumps [mypy](https://github.com/python/mypy) from 1.4.1 to 1.5.0.
- [Commits](https://github.com/python/mypy/compare/v1.4.1...v1.5.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-14 14:43:40 +00:00
Willi Ballenthin
1199fb94d4 Merge pull request #1723 from mandiant/dependabot/pip/tqdm-4.66.1
build(deps-dev): bump tqdm from 4.65.0 to 4.66.1
2023-08-14 16:43:18 +02:00
Willi Ballenthin
26fdbbd442 Merge pull request #1725 from mandiant/dependabot/pip/ruff-0.0.284
build(deps-dev): bump ruff from 0.0.282 to 0.0.284
2023-08-14 16:42:26 +02:00
Willi Ballenthin
737fab7969 elf: use equality not bit masking 2023-08-14 16:40:45 +02:00
dependabot[bot]
f6ee465a0a build(deps-dev): bump ruff from 0.0.282 to 0.0.284
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.282 to 0.0.284.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.282...v0.0.284)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-14 14:16:45 +00:00
dependabot[bot]
82f352f719 build(deps-dev): bump tqdm from 4.65.0 to 4.66.1
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.65.0 to 4.66.1.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.65.0...v4.66.1)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-14 14:16:16 +00:00
Yacine Elhamer
846bd62817 Merge remote-tracking branch 'parentrepo/dynamic-feature-extraction' into fix/issue-1711 2023-08-14 16:05:20 +02:00
Yacine
84cddc70fd Merge pull request #1709 from mandiant/fix/issue-1702
fix rendering of call and return addresses
2023-08-14 16:00:16 +03:00
Willi Ballenthin
2dc5295c0c Merge branch 'master' into fix/issue-1704 2023-08-14 13:15:23 +02:00
Willi Ballenthin
8479bc2f1f Merge pull request #1720 from mandiant/fix/issue-1705
elf: detect Android OS via note and dependencies
2023-08-14 13:11:23 +02:00
Capa Bot
7c1522d84d Sync capa-testfiles submodule 2023-08-14 11:11:05 +00:00
Willi Ballenthin
9afe19a096 changelog 2023-08-14 11:10:06 +00:00
Willi Ballenthin
bd5c65d22c elf: fix parsing of symtab from viv
closes #1704
2023-08-14 11:08:19 +00:00
Willi Ballenthin
e6cb3d3b3b os: detect Android via dependencies, too 2023-08-14 10:27:19 +00:00
Willi Ballenthin
18058beb0a changelog 2023-08-14 10:20:30 +00:00
Willi Ballenthin
8003547414 elf: detect Android OS via note
closes #1705
2023-08-14 10:13:42 +00:00
Yacine
2a83f1fc23 Merge pull request #1708 from mandiant/fix/issue-1707
tests: create workspaces only during tests, not import
2023-08-14 12:24:02 +03:00
Yacine Elhamer
751231b730 fixtures.py: fix the path of '0000a567' in get_data_path_by_name() method 2023-08-14 12:37:15 +03:00
Willi Ballenthin
c6d400bcf3 address: remove dynamic return address concept, as its unused today 2023-08-11 11:18:54 +00:00
Willi Ballenthin
fd1cd05b99 vverbose: render relevant scope at top of match tree
closes #1710
2023-08-11 10:59:44 +00:00
Willi Ballenthin
8202e9e921 main: don't use analysis flavor to filter rules
im worried this will interact poorly with our rule cache,
unless we add more handling there, which needs more testing.
so, since the filtering likely has only a small impact on performance,
revert the rule filtering changes for simplicity.
2023-08-11 10:36:59 +00:00
Willi Ballenthin
3c069a6784 rules: don't change passed-in argument
make a local copy of the scopes dict
2023-08-11 10:35:40 +00:00
Willi Ballenthin
e100a63cc8 rules: use set instead of tuple, add doc
since the primary operation is `contain()`,
set is more appropriate than tuple.
2023-08-11 10:34:41 +00:00
Willi Ballenthin
3057b5fb9d render: show analysis flavor
closes #1711
2023-08-11 09:49:13 +00:00
Willi Ballenthin
c91dc71e75 result document: wire analysis flavor through metadata
ref #1711
2023-08-11 09:33:30 +00:00
Willi Ballenthin
f48e4a8ad8 render: verbose: render dynamic call return address 2023-08-11 09:07:11 +00:00
Willi Ballenthin
dafbefb325 render: verbose: render call address
closes #1702
2023-08-11 09:02:29 +00:00
Willi Ballenthin
6de23a9748 tests: main: demonstrate CAPE analysis (and bug #1702) 2023-08-11 08:56:06 +00:00
Willi Ballenthin
1cf33e4343 tests: create workspaces only during tests, not import
closes #1707
2023-08-11 08:38:06 +00:00
Willi Ballenthin
34db63171f sync submodule testfiles 2023-08-11 08:36:29 +00:00
Capa Bot
ec93ca5b21 Sync capa rules submodule 2023-08-11 07:07:57 +00:00
colton-gabertan
2de6dc7cb8 Merge branch 'master' into backend-ghidra 2023-08-10 12:14:44 -07:00
Willi Ballenthin
19495f69d7 freeze: pydantic v2 fixes 2023-08-10 13:29:52 +00:00
Willi Ballenthin
c1fbb27d73 Merge branch 'master' into dynamic-feature-extraction 2023-08-10 13:21:49 +00:00
Willi Ballenthin
3cf748a135 vverbose: render both scopes nicely 2023-08-10 11:39:56 +02:00
Willi Ballenthin
85b58d041b process: simplify string enumeration loop 2023-08-10 11:38:43 +02:00
Willi Ballenthin
ae9d773e04 add TODO for typing.TypeAlias 2023-08-10 11:37:50 +02:00
Willi Ballenthin
582bb7c897 docstrings: improve wording 2023-08-10 11:36:51 +02:00
Capa Bot
e5efc158b7 Sync capa-testfiles submodule 2023-08-10 07:26:08 +00:00
Willi Ballenthin
9f436763f7 Merge pull request #1683 from Aayush-Goel-04/Aayush-Goel-04/Issue#331 2023-08-09 12:44:48 +02:00
Aayush Goel
a383022cff Update show-unused-features.py 2023-08-09 15:37:38 +05:30
Aayush Goel
57486733e7 Update scripts/show-unused-features.py
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-08-09 15:33:03 +05:30
Aayush Goel
df9828dd7f Update capa/rules/__init__.py
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-08-09 15:32:12 +05:30
Aayush Goel
d81f3a461e Update show-unused-features.py 2023-08-09 14:20:53 +05:30
Willi Ballenthin
f1e737ac92 Merge branch 'master' into Aayush-Goel-04/Issue#331 2023-08-09 08:53:02 +02:00
Mike Hunhoff
448aa9cd21 explorer: fix unhandled exception when resolving rule path (#1693) 2023-08-08 14:04:46 -06:00
colton-gabertan
f2c0509f81 Merge branch 'master' into backend-ghidra 2023-08-08 11:00:10 -07:00
Colton Gabertan
6287fbb958 Ghidra insn features (#1670)
* Implement Ghidra Instruction Feature Extraction
2023-08-08 10:45:14 -07:00
Aayush Goel
c497ad8253 Update show-unused-features.py 2023-08-08 18:36:25 +05:30
Aayush Goel
9c1aa2fc5d Update show-unused-features.py 2023-08-08 18:35:04 +05:30
Aayush Goel
f5a254f21f Merge branch 'master' into Aayush-Goel-04/Issue#331 2023-08-08 17:05:03 +05:30
Aayush Goel
fb3ae0267e Update scripts/show-unused-features.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-08-08 17:04:23 +05:30
Willi Ballenthin
5400576d4e Merge pull request #1689 from mandiant/dependabot/pip/ruff-0.0.282
build(deps-dev): bump ruff from 0.0.280 to 0.0.282
2023-08-08 11:02:54 +02:00
Willi Ballenthin
dabd9d0810 Merge pull request #1690 from mandiant/dependabot/pip/flake8-6.1.0
build(deps-dev): bump flake8 from 6.0.0 to 6.1.0
2023-08-08 11:02:24 +02:00
Willi Ballenthin
2bd777dbe4 Merge pull request #1691 from mandiant/dependabot/pip/types-protobuf-4.23.0.3
build(deps-dev): bump types-protobuf from 4.23.0.2 to 4.23.0.3
2023-08-08 11:02:12 +02:00
Willi Ballenthin
959c64b484 Merge pull request #1692 from mandiant/dependabot/pip/mypy-protobuf-3.5.0
build(deps-dev): bump mypy-protobuf from 3.4.0 to 3.5.0
2023-08-08 11:01:58 +02:00
Aayush Goel
232c9ce35c Add test for script & output rendered 2023-08-07 22:43:25 +05:30
Aayush Goel
b3a9763a32 Merge branch 'master' into Aayush-Goel-04/Issue#331 2023-08-07 21:02:42 +05:30
Aayush Goel
0fdc1dd3f5 Type Hints done , get_all_feature to Rule class 2023-08-07 21:00:29 +05:30
dependabot[bot]
80e224ec7c build(deps-dev): bump mypy-protobuf from 3.4.0 to 3.5.0
Bumps [mypy-protobuf](https://github.com/nipunn1313/mypy-protobuf) from 3.4.0 to 3.5.0.
- [Changelog](https://github.com/nipunn1313/mypy-protobuf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nipunn1313/mypy-protobuf/compare/v3.4.0...v3.5.0)

---
updated-dependencies:
- dependency-name: mypy-protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-07 14:42:44 +00:00
dependabot[bot]
75a4f309b4 build(deps-dev): bump types-protobuf from 4.23.0.2 to 4.23.0.3
Bumps [types-protobuf](https://github.com/python/typeshed) from 4.23.0.2 to 4.23.0.3.
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-07 14:42:39 +00:00
dependabot[bot]
358888178a build(deps-dev): bump flake8 from 6.0.0 to 6.1.0
Bumps [flake8](https://github.com/pycqa/flake8) from 6.0.0 to 6.1.0.
- [Commits](https://github.com/pycqa/flake8/compare/6.0.0...6.1.0)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-07 14:42:32 +00:00
dependabot[bot]
57e393bf7a build(deps-dev): bump ruff from 0.0.280 to 0.0.282
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.280 to 0.0.282.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.280...v0.0.282)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-07 14:42:21 +00:00
Capa Bot
eb7aa63be6 Sync capa rules submodule 2023-08-07 13:54:49 +00:00
Capa Bot
298a07dc07 Sync capa rules submodule 2023-08-07 13:31:25 +00:00
Capa Bot
f50a5e8efc Sync capa rules submodule 2023-08-07 13:28:05 +00:00
Yacine
d06b33e7ea Merge pull request #1687 from mandiant/fix-lint
lint.py: add default backend
2023-08-07 14:16:11 +01:00
mr-tz
9660f1e5ab add default backend 2023-08-07 14:00:30 +02:00
Willi Ballenthin
74d9b06835 Merge pull request #1679 from Aayush-Goel-04/Aayush-Goel-04/Issue#1582
bump pydantic to 2.1.1
2023-08-07 12:02:53 +02:00
Willi Ballenthin
681d4fb007 Merge pull request #1678 from yelhamer/call-scope
Add a call scope
2023-08-07 11:31:29 +02:00
Yacine Elhamer
a185341a4d features/address.py: rename CallAddress DynamicCallAddress 2023-08-07 09:48:11 +01:00
Yacine Elhamer
aacd9f51b3 delete empty files 2023-08-07 09:48:11 +01:00
Yacine
95148d445a test_rules.py: update rules' formatting
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-08-07 09:47:57 +01:00
Yacine
65ac422e36 test_rules.py: update rules' fomratting
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-08-07 09:47:37 +01:00
Willi Ballenthin
5ffb6ca0cd Merge branch 'dynamic-feature-extraction' into call-scope 2023-08-07 10:40:53 +02:00
Willi Ballenthin
85f151303a merge 2023-08-07 08:40:03 +00:00
Willi Ballenthin
216cd01b3c sync test data submodule 2023-08-07 08:37:23 +00:00
Yacine
23bd2e7cd4 cape/call.py: remove use of the description keyword for features
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-08-07 09:13:07 +01:00
Willi Ballenthin
5de055e2af Merge pull request #1677 from mandiant/fix/add-devcontainer-pre-commit
devcontainer: install pre-commit hooks
2023-08-07 10:01:20 +02:00
Willi Ballenthin
dd870a5cbd Merge pull request #1676 from mandiant/fix/issue-1675
linter: skip native API check for NtProtectVirtualMemory
2023-08-07 10:00:59 +02:00
Aayush Goel
a2254852b0 Update CHANGELOG.md 2023-08-06 22:55:54 +05:30
Aayush Goel
17aad56800 Script to get unused features
Used show_features.py script
2023-08-06 22:53:50 +05:30
Yacine Elhamer
f461f65a86 move thread-scope features into the call-scope 2023-08-06 18:12:29 +01:00
Capa Bot
2c8f99143a Sync capa-testfiles submodule 2023-08-05 16:40:13 +00:00
Capa Bot
ee68031d19 Sync capa-testfiles submodule 2023-08-05 16:37:46 +00:00
Yacine Elhamer
8dc4adbb5e fix test_rules.py yaml identation bug 2023-08-04 16:20:37 +01:00
Yacine Elhamer
8b36cd1e35 add call-scope tests 2023-08-04 16:20:37 +01:00
Aayush Goel
851da25560 Update bulk-process.py 2023-08-04 10:43:34 +05:30
Aayush Goel
a4b00b9064 remove exclude_none = True to not drop none fields 2023-08-04 10:26:56 +05:30
Aayush Goel
fd61456164 Update capa/features/freeze/__init__.py
Co-authored-by: Willi Ballenthin <wballenthin@google.com>
2023-08-04 09:07:13 +05:30
Aayush Goel
261baca683 updated deperecated functions 2023-08-04 01:35:41 +05:30
Aayush Goel
c7dde262ed remove initial instantiation for fields. 2023-08-03 22:40:01 +05:30
Yacine
cd700a1782 Merge branch 'dynamic-feature-extraction' into call-scope 2023-08-03 15:27:44 +01:00
Yacine
60e94adeb1 base_extractor.py: fix ProcessHandle documentation comment
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-08-03 14:39:53 +01:00
Yacine
eafed0f1d4 build_statements(): fix call-scope InvalidRule message typo
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-08-03 14:38:38 +01:00
Yacine Elhamer
7c14c51012 cape/call.py: update extract_call_features() comment 2023-08-03 14:20:18 +01:00
Aayush Goel
2bed3468f6 bump pydantic to 2.1.1 2023-08-03 17:21:46 +05:30
Yacine Elhamer
4f9d24598f bugfix 2023-08-03 11:24:24 +01:00
Yacine Elhamer
4277b4bef8 include an address' parent in comparisons 2023-08-03 11:21:58 +01:00
colton-gabertan
bab6c978fb Merge branch 'master' into backend-ghidra 2023-08-02 16:17:19 -07:00
Yacine Elhamer
3c3205adf1 add call address to show-features.py script 2023-08-02 23:10:27 +01:00
Yacine Elhamer
4e1527df95 update changelog 2023-08-02 22:48:38 +01:00
Yacine Elhamer
ca2760fb46 Initial commit 2023-08-02 22:46:54 +01:00
Willi Ballenthin
6647ecb6d4 Merge branch 'master' into fix/add-devcontainer-pre-commit 2023-08-02 15:02:15 +02:00
Willi Ballenthin
13533074ea devcontainer: install pre-commit hooks 2023-08-02 13:01:15 +00:00
Willi Ballenthin
a538a7bbab linter: skip native API check for more UEFI routines 2023-08-02 12:55:22 +00:00
Willi Ballenthin
b2789f0df6 Merge branch 'master' into fix/issue-1675 2023-08-02 14:49:32 +02:00
Willi Ballenthin
ab5c8b1129 linter: skip native API check for NtEnumerateSystemEnvironmentValuesEx 2023-08-02 12:49:17 +00:00
Capa Bot
149983dced Sync capa rules submodule 2023-08-02 12:42:03 +00:00
Willi Ballenthin
04fbcbbbd3 linter: skip native API check for NtProtectVirtualMemory
closes #1675
2023-08-02 12:36:42 +00:00
Willi Ballenthin
727ece499a Merge pull request #1662 from Aayush-Goel-04/Aayush-Goel-04/Issue#1607
ELF: Implement file import and export name extractor
2023-08-02 13:15:32 +02:00
Aayush Goel
62f50265bc Resolved Import address 2023-08-02 16:41:24 +05:30
Capa Bot
95ffdf19ff Sync capa rules submodule 2023-08-02 11:03:52 +00:00
Capa Bot
d18224eac6 Sync capa-testfiles submodule 2023-08-02 11:03:16 +00:00
Aayush Goel
26935ee6e6 Update test_elffile_features.py 2023-08-02 13:51:51 +05:30
Aayush Goel
f8c499fb43 Added test for elf import/export handling 2023-08-02 11:52:27 +05:30
Willi Ballenthin
61924672e2 Merge pull request #1671 from yelhamer/rule-statement-building 2023-08-01 22:15:03 +02:00
Yacine Elhamer
7fdd988e4f remove redundant imports 2023-08-01 20:12:15 +01:00
Yacine Elhamer
a85e0523f8 remove Scopes LRU caching 2023-08-01 20:09:42 +01:00
Aayush Goel
3bb5754b66 Update elffile.py 2023-08-01 22:41:11 +05:30
Aayush Goel
dd2eef52c3 Update elffile.py
remove enumerate
2023-08-01 22:21:00 +05:30
Willi Ballenthin
da45fb4bea Merge branch 'master' into Aayush-Goel-04/Issue#1607 2023-08-01 16:34:42 +02:00
Willi Ballenthin
7ed517a8f3 Merge pull request #1668 from mandiant/dependabot/pip/types-tabulate-0.9.0.3
build(deps-dev): bump types-tabulate from 0.9.0.1 to 0.9.0.3
2023-08-01 16:33:42 +02:00
Willi Ballenthin
f00e7426c5 Merge pull request #1667 from mandiant/dependabot/pip/types-requests-2.31.0.2
build(deps-dev): bump types-requests from 2.31.0.1 to 2.31.0.2
2023-08-01 16:33:12 +02:00
Willi Ballenthin
3f29c61038 Merge branch 'master' into dependabot/pip/types-requests-2.31.0.2 2023-08-01 16:33:04 +02:00
Willi Ballenthin
647ce67f7e Merge pull request #1666 from mandiant/dependabot/pip/types-protobuf-4.23.0.2
build(deps-dev): bump types-protobuf from 4.23.0.1 to 4.23.0.2
2023-08-01 16:32:29 +02:00
Willi Ballenthin
224923b8bd Merge pull request #1665 from mandiant/dependabot/pip/pyyaml-6.0.1
build(deps-dev): bump pyyaml from 6.0 to 6.0.1
2023-08-01 16:31:41 +02:00
Willi Ballenthin
8a08a93b1c Merge branch 'master' into dependabot/pip/pyyaml-6.0.1 2023-08-01 16:29:15 +02:00
Capa Bot
ed98bb3a57 Sync capa rules submodule 2023-08-01 11:21:32 +00:00
Capa Bot
d12185d851 Sync capa-testfiles submodule 2023-08-01 11:21:02 +00:00
Capa Bot
5f8280eb09 Sync capa rules submodule 2023-08-01 11:16:09 +00:00
Yacine Elhamer
462024ad03 update tests to explicitely specify scopes 2023-08-01 07:41:47 +01:00
Yacine Elhamer
f0d09899a1 rules/__init__.py: invalidate rules with no scopes field 2023-08-01 07:19:11 +01:00
Aayush Goel
30abe40999 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1607 2023-07-28 17:50:20 +05:30
Yacine Elhamer
b8212b3da7 main.py: replace | operator with Optional 2023-07-27 16:00:52 +01:00
Yacine Elhamer
3d812edc4d use weakrefs for Scopes instantiation; fix test_rules() 2023-07-27 15:52:39 +01:00
Yacine Elhamer
2efb7f2975 fix flake8 issues 2023-07-27 15:10:01 +01:00
Yacine Elhamer
44c5e96cf0 RuleSet: remove irrelevant rules after dependecies have been checked 2023-07-27 12:44:07 +01:00
Yacine Elhamer
97c878db22 update CHANGELOG 2023-07-27 10:33:34 +01:00
Yacine Elhamer
16e32f8441 add tests 2023-07-27 10:31:45 +01:00
Yacine Elhamer
d6aced5ec7 RulSet: add flavor-based rule filtering 2023-07-27 10:24:08 +01:00
colton-gabertan
0e58ec5176 Merge branch 'master' into backend-ghidra 2023-07-26 12:20:18 -07:00
Yacine Elhamer
b843382065 rules/__init__.py: update Scopes class 2023-07-26 17:20:51 +01:00
Willi Ballenthin
dd53349aea Merge pull request #1669 from xusheng6/master 2023-07-26 08:35:54 +02:00
Willi Ballenthin
d598faf145 Merge pull request #1664 from mandiant/dependabot/pip/ruff-0.0.280 2023-07-24 17:27:01 +02:00
dependabot[bot]
c265b1ca96 build(deps-dev): bump types-tabulate from 0.9.0.1 to 0.9.0.3
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.9.0.1 to 0.9.0.3.
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-24 14:15:59 +00:00
dependabot[bot]
b554eaf563 build(deps-dev): bump types-requests from 2.31.0.1 to 2.31.0.2
Bumps [types-requests](https://github.com/python/typeshed) from 2.31.0.1 to 2.31.0.2.
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-24 14:15:55 +00:00
dependabot[bot]
3d51b84bd1 build(deps-dev): bump types-protobuf from 4.23.0.1 to 4.23.0.2
Bumps [types-protobuf](https://github.com/python/typeshed) from 4.23.0.1 to 4.23.0.2.
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-24 14:15:50 +00:00
dependabot[bot]
684b2ded38 build(deps-dev): bump pyyaml from 6.0 to 6.0.1
Bumps [pyyaml](https://github.com/yaml/pyyaml) from 6.0 to 6.0.1.
- [Changelog](https://github.com/yaml/pyyaml/blob/6.0.1/CHANGES)
- [Commits](https://github.com/yaml/pyyaml/compare/6.0...6.0.1)

---
updated-dependencies:
- dependency-name: pyyaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-24 14:15:43 +00:00
dependabot[bot]
557e83b1dc build(deps-dev): bump ruff from 0.0.278 to 0.0.280
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.278 to 0.0.280.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.278...v0.0.280)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-24 14:15:37 +00:00
Xusheng
8f826cb92d Fix binja backend stack string detection. Re-enable binja stack string unit test 2023-07-24 19:15:35 +08:00
Aayush Goel
78a9909ec6 Update elffile.py
Updated changelog and added link references in comments
2023-07-23 15:30:37 +05:30
Willi Ballenthin
f4bdff0824 Merge pull request #1644 from yelhamer/find-dynamic-capabilities 2023-07-21 20:08:22 +02:00
Yacine Elhamer
d8c28e80eb add get_sample_hashes() to elf extractor 2023-07-21 15:50:09 +01:00
yelhamer
344b3e9931 Update capa/features/extractors/base_extractor.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-21 15:43:56 +01:00
yelhamer
c32ac19c0d Update capa/features/extractors/ida/extractor.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-21 15:43:41 +01:00
yelhamer
d13114e907 remove SampleHashes __iter__method
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-21 15:43:22 +01:00
yelhamer
90298fe2c8 Update capa/features/extractors/base_extractor.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-21 15:39:30 +01:00
Yacine Elhamer
3d1a1fb9fa add get_sample_hashes() to NullFeatureExtractor 2023-07-21 14:54:54 +01:00
Yacine Elhamer
830bad54bd fix bugs 2023-07-21 14:41:07 +01:00
Yacine Elhamer
c4ba5afe6b replace : FeatureSet annotations with a comment type annotation 2023-07-21 14:32:42 +01:00
Yacine Elhamer
4ec39d49aa fix linting issues 2023-07-21 14:03:57 +01:00
Yacine Elhamer
ab585ef951 add the skipif mark back 2023-07-21 14:00:58 +01:00
Yacine Elhamer
674122999f migrate the get_sample_hashes() function to each individual extractor 2023-07-21 14:00:01 +01:00
Yacine Elhamer
8085caef35 remove the usage of SampleHashes's __iter__() method 2023-07-21 13:48:48 +01:00
Yacine Elhamer
3ab3c61d5e use ida's hash-extraction functions 2023-07-21 13:48:48 +01:00
Yacine Elhamer
736b2cd689 address @mr-tz main.py review comments 2023-07-21 13:48:48 +01:00
yelhamer
bd8331678c update compute_static_layout with the appropriate types
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-21 13:16:51 +01:00
yelhamer
6f3fb42385 update compute_dynamic_layout with the appropriate type
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-21 13:15:55 +01:00
yelhamer
da4e887aee fix comment typo
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-07-21 12:40:02 +01:00
Yacine Elhamer
b1e468dae4 add tests for the get_sample_hashes() method 2023-07-21 11:04:21 +01:00
Yacine Elhamer
6d1a885864 update static freeze test 2023-07-21 08:48:18 +01:00
Yacine Elhamer
24b3abd706 add get_sample_hashes() to base extractor 2023-07-21 08:45:14 +01:00
yelhamer
806bc1853d Update mypy.ini: add TODO comment 2023-07-20 22:13:06 +01:00
Yacine Elhamer
6ee1dfd656 address review comments: rename SampleHashes's from_sample() method to from_bytes() method 2023-07-20 21:53:28 +01:00
Yacine Elhamer
ab092cb536 add sample_hashes attribute to the base extractors 2023-07-20 21:51:37 +01:00
Yacine Elhamer
b4cf50fb6e fix mypy issues 2023-07-20 21:48:05 +01:00
yelhamer
2b2b2b6545 Update capa/features/extractors/base_extractor.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-20 21:47:30 +01:00
yelhamer
fd7b926a33 Update capa/features/extractors/base_extractor.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-20 21:47:23 +01:00
Yacine Elhamer
482e0d386b use pathlib.Path() in binja and ida extractors 2023-07-20 21:42:14 +01:00
Yacine Elhamer
d99b16ed5e add copyright and remove old test 2023-07-20 21:41:16 +01:00
Yacine Elhamer
0a4fe58ac6 fix tests 2023-07-20 20:25:11 +01:00
Yacine Elhamer
8ac9caf45c fix bugs 2023-07-20 20:20:33 +01:00
Yacine Elhamer
1029b369f2 Merge remote-tracking branch 'parentrepo/dynamic-feature-extraction' into find-dynamic-capabilities 2023-07-20 20:02:49 +01:00
Willi Ballenthin
5ae588deaa Merge pull request #1658 from mandiant/sync-1657
sync
2023-07-20 14:05:22 +02:00
Willi Ballenthin
a2f31ab8ae update testfiles submodule 2023-07-20 11:52:15 +00:00
Willi Ballenthin
666c9c21a1 update testfiles submodule 2023-07-20 11:49:20 +00:00
Yacine Elhamer
a675c4c7a1 remove redundant code block 2023-07-20 11:27:07 +01:00
Yacine Elhamer
16eab6b5e5 remove unused commit 2023-07-20 11:24:07 +01:00
Yacine Elhamer
d520bfc753 fix bugs and add copyrights 2023-07-20 11:19:54 +01:00
Yacine Elhamer
301b10d261 fix style issues 2023-07-20 10:52:43 +01:00
Yacine Elhamer
e38e56ccf6 Merge remote-tracking branch 'parentrepo/dynamic-feature-extraction' into sync-1657 2023-07-20 09:33:48 +01:00
Mike Hunhoff
c0e126f812 merge upstream 2023-07-19 14:56:39 +00:00
yelhamer
7de223f116 Update capa/features/extractors/ida/extractor.py: add call to get_input_file_path()
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-19 15:39:06 +01:00
Capa Bot
4eabee7329 Sync capa rules submodule 2023-07-19 13:49:59 +00:00
Willi Ballenthin
0719273cee Merge pull request #1656 from RonnieSalomonsen/forward_export
rules: Add forwarded export characteristics to rule syntax under file…
2023-07-19 15:48:19 +02:00
Ronnie Salomonsen
de6bdf0621 Update CHANGELOG with fix for the new feature for forwarded export characteristics 2023-07-19 15:05:10 +02:00
Yacine Elhamer
c5d08ec0d1 update extractors and tests 2023-07-19 14:00:45 +01:00
Ronnie Salomonsen
1790dab1ab rules: Add forwarded export characteristics to rule syntax under file_scope 2023-07-19 11:27:52 +02:00
Yacine Elhamer
4e4b1235c3 mypy.ini: ignore proto issues 2023-07-18 21:04:51 +01:00
Yacine Elhamer
e5d7903475 add removed tests 2023-07-18 20:38:54 +01:00
Willi Ballenthin
781c33d13c Merge pull request #1652 from mandiant/williballenthin-patch-1
v6.0.0
2023-07-18 18:26:52 +02:00
Willi Ballenthin
70a1e66020 ci: publish: remove dev code 2023-07-18 14:02:35 +00:00
Willi Ballenthin
91b65d1d7f ci: publish: remove old commented code 2023-07-18 14:01:58 +00:00
Willi Ballenthin
a22dd65032 Merge branch 'master' into williballenthin-patch-1 2023-07-18 16:00:47 +02:00
Willi Ballenthin
3899662cbd v6.0.0 2023-07-18 14:00:09 +00:00
Willi Ballenthin
b73e1e3d7f pyproject: set readme context type 2023-07-18 13:56:04 +00:00
Willi Ballenthin
25624a1b46 ci: publish: dev release 2023-07-18 13:38:05 +00:00
Willi Ballenthin
e3c8cb74df ci: publish: dev release 2023-07-18 13:33:01 +00:00
Willi Ballenthin
f99824d996 v6.0.0a4 2023-07-18 13:22:11 +00:00
Willi Ballenthin
33cb81449c ci: publish: try to fix perm errors 2023-07-18 13:21:47 +00:00
Willi Ballenthin
c49385e681 Merge pull request #1651 from mandiant/williballenthin-patch-1
v6.0.0a3
2023-07-18 14:33:05 +02:00
Willi Ballenthin
5277f3b640 v6.0.0a3 2023-07-18 12:23:25 +00:00
Willi Ballenthin
dbfcbaa98e ci: publish: fix file name globbing 2023-07-18 12:23:15 +00:00
Willi Ballenthin
a2d70a12a9 Merge pull request #1650 from mandiant/williballenthin-patch-1
v6.0.0a2
2023-07-18 14:15:55 +02:00
Willi Ballenthin
be58f65ae5 v6.0.0a2 2023-07-18 11:37:45 +00:00
Willi Ballenthin
15caa9ee6e ci: publish: remove incorrect name 2023-07-18 13:35:24 +02:00
Willi Ballenthin
0398baa752 Merge pull request #1648 from mandiant/fix/issue-1622
prep v6.0.0a1
2023-07-18 13:30:43 +02:00
Willi Ballenthin
b1214df621 Merge branch 'master' into fix/issue-1622 2023-07-18 13:30:32 +02:00
Willi Ballenthin
c0ed955362 Merge pull request #1647 from mandiant/williballenthin-patch-1
contributing: document CLA
2023-07-18 12:53:48 +02:00
Yacine Elhamer
bc46bf3202 add vverbose rendering 2023-07-18 11:26:20 +01:00
Willi Ballenthin
1c6434a380 changelog: remove old formatting 2023-07-18 10:10:36 +00:00
Willi Ballenthin
fff1248ec4 changelog: fix links 2023-07-18 10:07:18 +00:00
Willi Ballenthin
14f0589194 v6.0.0a1 2023-07-18 10:04:39 +00:00
Willi Ballenthin
d47703fada v6.0 changelog 2023-07-18 10:02:07 +00:00
Willi Ballenthin
faf3ca53f7 changelog 2023-07-18 09:21:51 +00:00
Willi Ballenthin
18e0408577 contributing: document CLA 2023-07-18 11:18:28 +02:00
Willi Ballenthin
972fbe7290 Merge pull request #1641 from mandiant/fix/issue-1624
forwarded export features
2023-07-18 10:55:30 +02:00
Willi Ballenthin
40793eeefb tests: bn: update link to tracking issue 2023-07-17 18:07:25 +02:00
Willi Ballenthin
221a5a9f03 tests: xfail binja forwarded exports 2023-07-17 17:56:33 +02:00
Willi Ballenthin
d1f5a6e76b Merge branch 'fix/issue-1624' of personal.github.com:mandiant/capa into fix/issue-1624 2023-07-17 17:35:47 +02:00
Willi Ballenthin
d2567692a8 factor out common forwarded export name normalization 2023-07-17 17:32:40 +02:00
Colton Gabertan
6fa7f24818 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
2023-07-17 09:00:03 -06:00
yelhamer
4af84e53d5 bugfixes 2023-07-17 12:25:12 +01:00
Yacine Elhamer
e3f60ea0fb initial commit 2023-07-17 11:50:49 +01:00
Mike Hunhoff
68caece2fa fix linting errors 2023-07-13 18:49:52 +00:00
Mike Hunhoff
94aaaa297d remove stale is_runtime_ida function 2023-07-13 18:16:11 +00:00
Mike Hunhoff
6ce897e39b merge upstream 2023-07-13 17:57:34 +00:00
Willi Ballenthin
7c67fae52a changelog: formatting 2023-07-13 16:53:35 +02:00
Willi Ballenthin
ebae5e5ca0 Merge branch 'master' into fix/issue-1624 2023-07-13 16:51:41 +02:00
Capa Bot
244d56e32a Sync capa-testfiles submodule 2023-07-13 14:50:40 +00:00
Willi Ballenthin
5f2b92de40 Merge branch 'master' into fix/issue-1624 2023-07-13 16:50:35 +02:00
Capa Bot
1065ff9779 Sync capa-testfiles submodule 2023-07-13 14:49:40 +00:00
Willi Ballenthin
5253ad7014 Merge pull request #1640 from mandiant/fix/issue-1592
tests: make fixtures available via conftest.py
2023-07-13 15:39:11 +02:00
Willi Ballenthin
82223dcdc9 conftest: isort 2023-07-13 13:12:13 +00:00
Willi Ballenthin
724f9e4b81 conftest: isort 2023-07-13 14:52:05 +02:00
Willi Ballenthin
c4da4bcfe7 conftest: update noqa ignores 2023-07-13 14:35:09 +02:00
Willi Ballenthin
fd36946c4b conftest: import symbols prefixed with _ 2023-07-13 14:32:24 +02:00
Willi Ballenthin
8c9853ad12 Merge pull request #1639 from mandiant/fix/issue-1636
main: don't show spinner when debug messages are emitted
2023-07-13 13:47:55 +02:00
Willi Ballenthin
562a61930d Merge pull request #1635 from mandiant/feat/ci-toplevel-permissions
ci: set top level permissions to satisfy code scanning
2023-07-13 13:20:06 +02:00
Willi Ballenthin
f9d210367e Merge pull request #1638 from mandiant/feat/issue-1290
main: log time taken to analyze each function
2023-07-13 13:19:53 +02:00
Willi Ballenthin
bb6557ea0a ida: extract forwarded export features 2023-07-13 12:18:57 +02:00
Willi Ballenthin
cb8133467b Merge branch 'fix/issue-1624' of personal.github.com:mandiant/capa into fix/issue-1624 2023-07-13 11:55:56 +02:00
Willi Ballenthin
718813bc1c Merge branch 'master' into fix/issue-1624 2023-07-13 16:16:40 +02:00
Willi Ballenthin
394c3807c1 Merge branch 'master' into fix/issue-1624 2023-07-13 11:55:46 +02:00
Willi Ballenthin
74924990a2 changelog 2023-07-13 11:50:56 +02:00
Willi Ballenthin
330f2a6b9b viv: emit forwarded export features
ref #1592
2023-07-13 11:47:32 +02:00
Willi Ballenthin
6b81c77d22 profile-time: workaround for flake8-encodings bug
https://github.com/python-formate/flake8-encodings/issues/35
2023-07-13 11:45:53 +02:00
Willi Ballenthin
9e9f120c80 pefile: better handle forwarded exports with specific paths 2023-07-13 10:51:28 +02:00
Capa Bot
546789fea6 Sync capa rules submodule 2023-07-13 08:47:01 +00:00
Willi Ballenthin
76901ced19 Merge pull request #1634 from mandiant/feat/faster-py-tests
ci: use latest python for best performance
2023-07-13 10:45:48 +02:00
Willi Ballenthin
c29d0a4f56 Update .github/workflows/tests.yml
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-07-13 10:45:43 +02:00
Willi Ballenthin
6b6d7eb494 pefile: extract forwarded exports 2023-07-13 10:32:27 +02:00
Willi Ballenthin
21b2aac8b5 fixtures: add test cases for forwarded exports 2023-07-13 10:31:52 +02:00
Willi Ballenthin
7898ac24d5 show-features: support showing pefile features 2023-07-13 10:31:28 +02:00
Willi Ballenthin
5a3775455b main: allow to specify --backend=pefile 2023-07-13 10:30:43 +02:00
Willi Ballenthin
892cd48713 Merge pull request #1633 from mandiant/dependabot/pip/ruff-0.0.278
build(deps-dev): bump ruff from 0.0.277 to 0.0.278
2023-07-13 10:24:56 +02:00
dependabot[bot]
c062115366 build(deps-dev): bump ruff from 0.0.277 to 0.0.278
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.277 to 0.0.278.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.277...v0.0.278)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-13 08:19:29 +00:00
Willi Ballenthin
ff7a006ba1 Merge pull request #1632 from mandiant/feat/issue-1594
update copyright and license headers
2023-07-13 10:18:50 +02:00
Willi Ballenthin
7665d56f93 Merge branch 'master' into feat/issue-1594 2023-07-13 10:18:44 +02:00
Capa Bot
280e253286 Sync capa rules submodule 2023-07-13 08:15:43 +00:00
Willi Ballenthin
7edf126a63 Merge pull request #1631 from mandiant/feat/issue-1599
introduce flake8-use-pathlib
2023-07-13 10:15:24 +02:00
Willi Ballenthin
ad6b475dfe Merge pull request #1630 from mandiant/fix/issue-1629
fix binja test type error
2023-07-13 10:14:22 +02:00
Capa Bot
f897f00227 Sync capa-testfiles submodule 2023-07-13 08:11:11 +00:00
Willi Ballenthin
ea3090a066 changelog 2023-07-13 09:39:04 +02:00
Willi Ballenthin
b9090b86ce tests: make fixtures available via conftest.py
closes #1592
2023-07-13 09:37:39 +02:00
Capa Bot
5088f45b6a Sync capa-testfiles submodule 2023-07-13 07:19:20 +00:00
Capa Bot
ea51801806 Sync capa-testfiles submodule 2023-07-13 07:06:30 +00:00
Willi Ballenthin
04db034895 changelog 2023-07-13 08:49:46 +02:00
Willi Ballenthin
b547987b33 main: don't show spinner when debug messages are emitted
closes #1636
2023-07-13 08:47:14 +02:00
Willi Ballenthin
0511ef7093 changelog 2023-07-13 06:26:25 +02:00
Willi Ballenthin
e9ccc5276a main: log time taken to analyze each function
closes #1290
2023-07-13 06:24:22 +02:00
Willi Ballenthin
36a840cb2c ci: set top level permissions to satisfy code scanning 2023-07-13 06:12:42 +02:00
Willi Ballenthin
797021874b ci: use latest python for best performance 2023-07-13 05:37:22 +02:00
Willi Ballenthin
2370c5b50d Merge branch 'master' of personal.github.com:mandiant/capa into feat/issue-1594 2023-07-13 05:19:38 +02:00
Willi Ballenthin
b285985a79 flake8: configure copyright header for our project
closes #1594
2023-07-13 05:16:59 +02:00
Willi Ballenthin
59bd930881 fix merge 2023-07-13 05:04:26 +02:00
Willi Ballenthin
c86ab51210 fix copyright headers everywhere 2023-07-13 05:03:33 +02:00
Willi Ballenthin
e987fc2034 flake8: initial copyright config 2023-07-13 04:57:36 +02:00
Willi Ballenthin
7550cc8466 introduce flake8-use-pathlib 2023-07-13 04:31:20 +02:00
Willi Ballenthin
acaf6c1272 main: add type hints for main 2023-07-13 04:25:01 +02:00
Willi Ballenthin
a28000b41a Merge branch 'master' into fix/issue-1629 2023-07-13 04:24:51 +02:00
Willi Ballenthin
560dc358fa Merge branch 'master' into fix/issue-1629 2023-07-13 04:20:04 +02:00
Willi Ballenthin
a32f2cc0f8 tests: fix type error 2023-07-13 04:19:09 +02:00
Mike Hunhoff
eeb0f78564 merge upstream 2023-07-12 17:57:35 +00:00
Moritz
ce15a2b01e Merge pull request #1580 from yelhamer/analysis-flavor
add flavored scopes
2023-07-12 17:24:38 +02:00
Colton Gabertan
97c2005661 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
2023-07-12 08:58:35 -06:00
Yacine Elhamer
9c878458b8 fix typo: replace 'rules' with 'rule' 2023-07-12 15:43:32 +01:00
Yacine Elhamer
53d897da09 ida/plugin/form.py: replace list comprehension in any() with a generator 2023-07-12 15:39:56 +01:00
Yacine Elhamer
17030395c6 ida/plugin/form.py: replace usage of '==' with usage of 'in' operator 2023-07-12 15:36:28 +01:00
Yacine Elhamer
34d3d6c1f9 Merge remote-tracking branch 'origin/analysis-flavor' into yelhamer-analysis-flavor 2023-07-12 15:27:13 +01:00
Capa Bot
87a6459278 Sync capa rules submodule 2023-07-12 10:13:13 +00:00
Willi Ballenthin
4e02e36d2c Merge pull request #1628 from mandiant/feat/flake8-simplify
introduce flake8-simplify
2023-07-12 12:12:53 +02:00
Willi Ballenthin
a35bf4c807 Merge pull request #1626 from mandiant/dependabot/pip/black-23.7.0
build(deps-dev): bump black from 23.3.0 to 23.7.0
2023-07-12 11:44:37 +02:00
Willi Ballenthin
a106953fec Merge pull request #1627 from mandiant/dependabot/pip/flake8-bugbear-23.7.10
build(deps-dev): bump flake8-bugbear from 23.6.5 to 23.7.10
2023-07-12 11:44:26 +02:00
Willi Ballenthin
65e8300145 introduce flake8-simplify 2023-07-12 11:40:44 +02:00
Capa Bot
7526ff876f Sync capa-testfiles submodule 2023-07-12 09:09:04 +00:00
Capa Bot
78a6d9a511 Sync capa rules submodule 2023-07-12 09:06:40 +00:00
Willi Ballenthin
e335c9f977 Merge pull request #1612 from yelhamer/process-thread-addresses
add process and thread addresses
2023-07-12 10:54:14 +02:00
dependabot[bot]
2343e73f41 build(deps-dev): bump flake8-bugbear from 23.6.5 to 23.7.10
Bumps [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) from 23.6.5 to 23.7.10.
- [Release notes](https://github.com/PyCQA/flake8-bugbear/releases)
- [Commits](https://github.com/PyCQA/flake8-bugbear/compare/23.6.5...23.7.10)

---
updated-dependencies:
- dependency-name: flake8-bugbear
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-12 08:51:34 +00:00
dependabot[bot]
aae2e51688 build(deps-dev): bump black from 23.3.0 to 23.7.0
Bumps [black](https://github.com/psf/black) from 23.3.0 to 23.7.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.3.0...23.7.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-12 08:51:25 +00:00
Willi Ballenthin
fe57016abd Merge pull request #1619 from mandiant/dependabot/pip/protobuf-4.23.4
build(deps-dev): bump protobuf from 4.23.2 to 4.23.4
2023-07-12 10:51:02 +02:00
Willi Ballenthin
de8bba41dc Merge pull request #1620 from mandiant/dependabot/pip/ruff-0.0.277
build(deps-dev): bump ruff from 0.0.275 to 0.0.277
2023-07-12 10:50:48 +02:00
Willi Ballenthin
90a2fd936c Merge pull request #1623 from Aayush-Goel-04/Aayush-Goel-04/Issue#1534
Updated file paths to use pathlib.Path instance
2023-07-12 10:50:29 +02:00
Capa Bot
deb6114530 Sync capa rules submodule 2023-07-11 20:38:54 +00:00
Yacine Elhamer
4ee38cbe29 fix linting issues 2023-07-11 14:52:04 +01:00
Yacine Elhamer
12c9154f55 fix flake8 linting issues 2023-07-11 14:40:56 +01:00
Yacine Elhamer
0e312d6dfe replace unused variable 'r' with '_' 2023-07-11 14:38:52 +01:00
Yacine Elhamer
7e18eeddba update ruff.toml 2023-07-11 14:33:19 +01:00
Yacine Elhamer
0db7141e33 remove redundant import 2023-07-11 14:33:07 +01:00
Yacine Elhamer
1ef0b16f11 Update ruff.toml 2023-07-11 14:32:33 +01:00
Yacine Elhamer
37c1bf98eb fix ruff F401 pytes issues 2023-07-11 14:26:59 +01:00
Yacine Elhamer
85d4c00096 fix ruff linting issues with test_static_freeze 2023-07-11 14:07:08 +01:00
Yacine Elhamer
078978a5b5 fix fixtures issue 2023-07-11 13:33:48 +01:00
Yacine Elhamer
841d393f8b fix non-matching type issue 2023-07-11 12:49:15 +01:00
Yacine Elhamer
740d1f6d4e fix imports: import TypeAlias from typing_extensions 2023-07-11 12:40:58 +01:00
Yacine Elhamer
b615c103ef fix flake8 linting: replace unused 'variable' with '_' 2023-07-11 12:37:01 +01:00
Yacine Elhamer
f879f53a6b fix linting issues 2023-07-11 12:33:37 +01:00
Yacine Elhamer
42baa10bcb Merge branch 'process-thread-addresses' of https://github.com/yelhamer/capa into yelhamer-process-thread-addresses 2023-07-11 12:07:20 +01:00
Willi Ballenthin
d438b90879 Merge branch 'master' into Aayush-Goel-04/Issue#1534 2023-07-11 12:30:13 +02:00
Yacine Elhamer
6feb9f540f fix ruff linting issues 2023-07-11 10:58:00 +01:00
Yacine Elhamer
f86ecfe446 Merge remote-tracking branch 'parentrepo/dynamic-feature-extraction' into analysis-flavor 2023-07-11 10:43:31 +01:00
Capa Bot
c1cd272865 Sync capa-testfiles submodule 2023-07-11 08:29:10 +00:00
Capa Bot
fdb53d97ce Sync capa-testfiles submodule 2023-07-11 08:28:43 +00:00
Capa Bot
db5e735928 Sync capa-testfiles submodule 2023-07-11 08:28:27 +00:00
colton-gabertan
785825d77e Merge branch 'master' into backend-ghidra 2023-07-11 01:00:55 -07:00
Aayush Goel
1baa7a5e4b flake8 checks resolved 2023-07-11 02:30:09 +05:30
Aayush Goel
ef39bc3c3a Merged Changes from PR #1591 2023-07-11 01:14:38 +05:30
Aayush Goel
8e346cb411 Merge branch 'Aayush-Goel-04/Issue#1534' of https://github.com/Aayush-Goel-04/capa into Aayush-Goel-04/Issue#1534 2023-07-11 00:59:21 +05:30
Aayush Goel
d1a1c6875b extractors accept Path instance 2023-07-11 00:41:36 +05:30
Capa Bot
b84af6a205 Sync capa rules submodule 2023-07-10 15:27:03 +00:00
Yacine Elhamer
64a16314ab Update capa/features/address.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-07-10 16:24:30 +01:00
Yacine Elhamer
dccebaeff8 Update CHANGELOG.md: include PR number 2023-07-10 16:18:59 +01:00
Yacine Elhamer
d2e5dea3e2 update magic header 2023-07-10 16:15:37 +01:00
Yacine Elhamer
ec59886031 Update capa/rules/__init__.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-10 15:58:27 +01:00
Yacine Elhamer
917dd8b0db Update scripts/lint.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-10 15:58:17 +01:00
Willi Ballenthin
160c662e7c Merge pull request #1621 from mandiant/dependabot/pip/flake8-comprehensions-3.14.0
build(deps-dev): bump flake8-comprehensions from 3.13.0 to 3.14.0
2023-07-10 16:52:41 +02:00
Yacine Elhamer
63e273efd4 fix bugs and mypy issues 2023-07-10 15:52:33 +01:00
dependabot[bot]
015056c54a build(deps-dev): bump flake8-comprehensions from 3.13.0 to 3.14.0
Bumps [flake8-comprehensions](https://github.com/adamchainz/flake8-comprehensions) from 3.13.0 to 3.14.0.
- [Changelog](https://github.com/adamchainz/flake8-comprehensions/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/adamchainz/flake8-comprehensions/compare/3.13.0...3.14.0)

---
updated-dependencies:
- dependency-name: flake8-comprehensions
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 14:37:18 +00:00
dependabot[bot]
babf99ea48 build(deps-dev): bump ruff from 0.0.275 to 0.0.277
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.275 to 0.0.277.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.275...v0.0.277)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 14:36:34 +00:00
dependabot[bot]
c8f5496008 build(deps-dev): bump protobuf from 4.23.2 to 4.23.4
Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 4.23.2 to 4.23.4.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl)
- [Commits](https://github.com/protocolbuffers/protobuf/compare/v4.23.2...v4.23.4)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 14:35:50 +00:00
Yacine Elhamer
9394194031 address review comments 2023-07-10 14:12:56 +01:00
Yacine Elhamer
af256bc0e9 fix mypy issues and bugs 2023-07-10 14:11:10 +01:00
Yacine Elhamer
37e4b913b0 address review comments 2023-07-10 13:22:47 +01:00
Willi Ballenthin
aa8055229d Merge pull request #1617 from mandiant/fix/issue-1616
ci: restrict permissions of GITHUB_TOKEN
2023-07-10 14:13:33 +02:00
Willi Ballenthin
454b6d1aca Merge branch 'master' into fix/issue-1616 2023-07-10 14:03:39 +02:00
Yacine Elhamer
722ee2f3d0 remove redundant print
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-10 12:54:15 +01:00
Yacine Elhamer
e5f5d542d0 replace ppid and pid fields with process in thread address
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-10 12:53:27 +01:00
Willi Ballenthin
1373fabf02 Merge pull request #1613 from mandiant/fix/issue-1491
PyPI trusted publishing
2023-07-10 13:48:24 +02:00
Willi Ballenthin
320539bd26 Merge branch 'master' into fix/issue-1491 2023-07-10 13:48:15 +02:00
Willi Ballenthin
ac12d5a7e2 Merge pull request #1611 from mandiant/fix/issue-1301
migrate to pyproject.toml
2023-07-10 13:45:50 +02:00
Yacine Elhamer
1ac64aca10 feature freeze: fix Addres.from_capa() not returning bug 2023-07-10 12:44:27 +01:00
Yacine Elhamer
78054eea5a update changelog 2023-07-10 12:18:16 +01:00
Yacine Elhamer
ff63b0ff1a rename test_freeze.py to test_static_freeze.py 2023-07-10 12:15:38 +01:00
Yacine Elhamer
e2e367f091 update tests 2023-07-10 12:15:06 +01:00
Yacine Elhamer
5aa1a1afc7 initial commit: add ProcessAddress and ThreadAddress 2023-07-10 12:14:53 +01:00
Willi Ballenthin
506d677684 Merge pull request #1591 from mandiant/fix/issue-1579
use pre-commit to invoke linters
2023-07-10 11:58:01 +02:00
Willi Ballenthin
f983307c97 Merge branch 'master' into fix/issue-1579 2023-07-10 11:57:51 +02:00
Capa Bot
a712bf3389 Sync capa rules submodule 2023-07-10 09:57:25 +00:00
Willi Ballenthin
a2d6bd693b Merge branch 'dynamic-feature-extraction' into analysis-flavor 2023-07-10 10:23:49 +02:00
Willi Ballenthin
7f57fccefb fix lints after sync with master 2023-07-10 02:55:50 +02:00
Willi Ballenthin
72e123e319 sync master 2023-07-10 02:50:18 +02:00
Willi Ballenthin
d29e7140b6 Merge pull request #1596 from mandiant/sync-master
Sync master
2023-07-10 10:30:23 +02:00
Willi Ballenthin
dc1f2e728d ci: restrict permissions of GITHUB_TOKEN
closes #1616
2023-07-10 02:43:48 +02:00
Willi Ballenthin
1f8aa7cfe1 changelog 2023-07-10 02:07:19 +02:00
Willi Ballenthin
81b964386f ci: publish to PyPI using trusted publishing
closes #1491
2023-07-10 02:06:06 +02:00
Willi Ballenthin
cb289e3fc5 ci: publish: use trusted publishing 2023-07-10 01:57:42 +02:00
Willi Ballenthin
fb176196eb changelog 2023-07-10 01:46:06 +02:00
Willi Ballenthin
dd2bbc9a48 migrate to pyproject.toml
closes #1301
2023-07-10 01:44:38 +02:00
Willi Ballenthin
118b955e10 features: fix circular import 2023-07-09 23:59:45 +02:00
Willi Ballenthin
d89dd499b6 add issue links for TODOs 2023-07-09 23:55:36 +02:00
Willi Ballenthin
430f9da449 Merge branch 'master' into fix/issue-1579 2023-07-10 11:09:25 +02:00
Willi Ballenthin
ae10a2ea34 introduce flake8-todos linter 2023-07-09 23:35:52 +02:00
Willi Ballenthin
4a49543d12 introduce flake8-print linter 2023-07-09 22:44:47 +02:00
Willi Ballenthin
106b12e2a4 move flake8 config to its own config file 2023-07-09 22:35:53 +02:00
Willi Ballenthin
7fe738e28f introduce flake8-no-implicit-concat linter 2023-07-09 22:18:01 +02:00
Willi Ballenthin
54203f3be9 introduce flake8-logging-format linter 2023-07-09 22:11:46 +02:00
Aayush Goel
a949698b86 Update fixtures.py
Dealt with encoding methods for how "ping_täst" file name is read.
2023-07-09 17:47:09 +05:30
Aayush Goel
673af45c55 Update args.sample type to Path and str vs as_posix comparisons 2023-07-09 16:02:28 +05:30
Aayush Goel
e0ed8c6e04 Resolved the suggestions. 2023-07-08 13:51:41 +05:30
Capa Bot
fc1dd401d2 Sync capa rules submodule 2023-07-08 07:53:28 +00:00
colton-gabertan
d452fdeca5 Merge branch 'master' into backend-ghidra 2023-07-08 00:20:47 -07:00
mr-tz
b6580f99db sync submodule 2023-07-07 19:37:25 +02:00
Yacine Elhamer
605fbaf803 add import asdict from dataclasses 2023-07-07 15:33:05 +01:00
Yacine Elhamer
03b0493d29 Scopes class: remove __eq__ operator overriding and override __in__ instead 2023-07-07 15:31:45 +01:00
Yacine Elhamer
5e295f59a4 DEV_SCOPE: add todo comment 2023-07-07 15:31:45 +01:00
mr-tz
f3135630d1 Merge branch 'master' into sync-master 2023-07-07 14:28:13 +02:00
Moritz
4a2902512e Update test_binja_features.py (#1595)
temporarily skip stack string test, while we wait for #1473
2023-07-07 14:01:50 +02:00
Moritz
e140fba5df enhance various dynamic-related functions (#1590)
* enhance various dynamic-related functions

* test_cape_features(): update API(NtQueryValueKey) feature count to 7

---------

Co-authored-by: Yacine Elhamer <elhamer.yacine@gmail.com>
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-07 13:59:12 +02:00
Yacine Elhamer
fa7a7c294e replace usage of __dict__ with dataclasses.asdict()
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-07-07 11:01:02 +01:00
Yacine Elhamer
9dd65bfcb9 extract_subscope_rules(): use DEV_SCOPE 2023-07-07 08:54:19 +01:00
Aayush Goel
a8f1067f8a Fixed Path issue in cache-ruleset.py 2023-07-07 12:39:18 +05:30
Aayush Goel
ef9b0737a8 Merge branch 'master' into Aayush-Goel-04/Issue#1534 2023-07-07 12:05:57 +05:30
Aayush Goel
6218f31ea2 Update CHANGELOG.md
Update CHANGELOG.md

Update CHANGELOG.md

Update CHANGELOG.md
2023-07-07 12:03:05 +05:30
Aayush Goel
14924174c5 convert str(path) usage to path.as_posix() to get str format of Path
Update fixtures.py
2023-07-07 12:03:05 +05:30
Aayush Goel
edeb458b33 some more changes 2023-07-07 12:03:05 +05:30
Capa Bot
b8f277b3c6 Sync capa-testfiles submodule 2023-07-07 06:26:53 +00:00
Capa Bot
5bc85f39a6 Sync capa rules submodule 2023-07-07 06:26:34 +00:00
Colton Gabertan
51ffb1d75c Add Ghidra File Feature Extraction (#1564)
Implement Ghidra backend file feature extraction
2023-07-06 17:05:08 -07:00
colton-gabertan
1f631b3ed1 bump min Python3 version to 3.8 2023-07-06 15:42:04 -07:00
colton-gabertan
1ea91d60ac Merge branch 'master' into backend-ghidra 2023-07-06 15:40:09 -07:00
Willi Ballenthin
13a8e252f0 introduce flake8-comprehensions 2023-07-06 20:04:27 +02:00
Willi Ballenthin
ff47270681 add flake8-encoding plugin 2023-07-06 19:42:57 +02:00
Willi Ballenthin
3ad4de70bf gitignore 2023-07-06 19:35:17 +02:00
Willi Ballenthin
9f6165f65c doc: installation: better enumerate current linters 2023-07-06 19:34:07 +02:00
Willi Ballenthin
982dc46623 add flake8-bugbear linter 2023-07-06 19:30:51 +02:00
Yacine Elhamer
a8f722c4de xfail tests that require the old ruleset 2023-07-06 18:15:02 +01:00
Willi Ballenthin
a43d2c115f tests: fix fixture imports 2023-07-06 19:04:53 +02:00
Yacine Elhamer
0c56291e4a update linter 2023-07-06 17:50:57 +01:00
Yacine Elhamer
c916e3b07f update the linter 2023-07-06 17:27:45 +01:00
Yacine Elhamer
32f936ce8c address review comments 2023-07-06 17:17:18 +01:00
Willi Ballenthin
e675bef062 ci: invoke linter directly 2023-07-06 18:14:14 +02:00
Willi Ballenthin
511aa0fb51 doc: installation: more details on pre-commit 2023-07-06 18:11:58 +02:00
Willi Ballenthin
90e607fe9a flake8 2023-07-06 18:11:48 +02:00
Willi Ballenthin
9441da4887 isort 2023-07-06 17:50:34 +02:00
Willi Ballenthin
47074fd129 fix ruff issues 2023-07-06 17:49:40 +02:00
Willi Ballenthin
adbfb8db06 doc: installation: document pre-commit 2023-07-06 17:18:36 +02:00
Willi Ballenthin
8c8601197b changelog 2023-07-06 17:15:16 +02:00
Willi Ballenthin
3ca233e0bd Merge branch 'master' into fix/issue-1579 2023-07-07 10:46:09 +02:00
Willi Ballenthin
f17edb3151 ci: use pre-commit to invoke linters 2023-07-06 17:12:19 +02:00
Willi Ballenthin
691ef1c72f remove old linter configs 2023-07-06 17:12:00 +02:00
Willi Ballenthin
75a76b47be setup: add pre-commit dev dependency 2023-07-06 17:11:37 +02:00
Willi Ballenthin
6f0d1f7518 add pre-commit config 2023-07-06 17:10:54 +02:00
Willi Ballenthin
25a6d78b88 ruff: update config 2023-07-06 16:32:31 +02:00
Willi Ballenthin
65e309450d Merge pull request #1588 from mandiant/fix/feature-1586
use fancy box drawing characters for default output
2023-07-06 15:26:24 +02:00
Willi Ballenthin
51292880fd Merge branch 'master' into fix/feature-1586 2023-07-06 15:26:08 +02:00
Willi Ballenthin
26998efead Merge pull request #1589 from mandiant/fix/dont-leave-tqdm
main: don't leave behind traces of the progress bar
2023-07-06 15:22:48 +02:00
Willi Ballenthin
cf9421aabf Merge branch 'master' into fix/dont-leave-tqdm 2023-07-06 15:22:42 +02:00
Willi Ballenthin
e53fd8d6c8 Merge pull request #1587 from mandiant/fix/issue-1578
bump minimum python version to 3.8
2023-07-06 15:22:07 +02:00
Willi Ballenthin
b62c011823 Merge branch 'master' into fix/issue-1578 2023-07-06 14:36:58 +02:00
Willi Ballenthin
f9248262f5 Merge branch 'master' into fix/dont-leave-tqdm 2023-07-06 14:36:43 +02:00
Moritz
bbafedc992 Merge pull request #1585 from mandiant/fix/issue-1584
fix import-to-ida due to changes in the result document format in v5
2023-07-06 14:33:01 +02:00
Capa Bot
46ff798fae Sync capa-testfiles submodule 2023-07-06 09:26:23 +00:00
Colton Gabertan
c5f51e03f4 ghidra: Add Global Feature Extraction (#1526)
* Revert "colton: removed redundant imports & object, locally tested"

This reverts commit 3da233dcad.

* removed redundant imports & objects, local test confirmation

* linted with isort

* linted with black

* linted with pycodestyle

* additional linting

* rebasing to avoid merge conflicts
2023-07-06 01:27:37 -07:00
Capa Bot
b57188e98c Sync capa rules submodule 2023-07-06 08:17:32 +00:00
Capa Bot
49ffbdd54d Sync capa-testfiles submodule 2023-07-06 08:04:33 +00:00
Colton Gabertan
855463b319 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
2023-07-05 18:48:45 -06:00
Aayush Goel
62db346b49 Style , mypy checks 2023-07-06 05:28:13 +05:30
Yacine Elhamer
47aebcbdd4 fix show-capabilities-by-function 2023-07-06 00:48:22 +01:00
Aayush Goel
20e7acaa1a Update CHANGELOG.md 2023-07-06 05:16:27 +05:30
Aayush Goel
c0d712acea Changes os.path to pathlib.Path usage
changed args.rules , args.signatures types in handle_common_args.
2023-07-06 05:12:50 +05:30
Yacine Elhamer
4649c9a61d rename rule.scope to rule.scope in ida plugin 2023-07-06 00:09:23 +01:00
Yacine Elhamer
9300e68225 fix mypy issues in test_rules.py 2023-07-06 00:05:20 +01:00
Yacine Elhamer
19e40a3383 address review comments 2023-07-05 23:58:08 +01:00
Aayush Goel
66e2a225d2 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1534 2023-07-06 02:21:11 +05:30
Willi Ballenthin
2e27745b5f setup: bump mypy hints for colorama 2023-07-05 19:30:55 +02:00
Willi Ballenthin
b5a063b0d9 pep8 2023-07-05 19:19:26 +02:00
Willi Ballenthin
ba8040ace5 main: remove old codec registration for py3.7 2023-07-05 19:15:33 +02:00
Willi Ballenthin
9bcd7678a4 main: fix console output on windows (in CI) 2023-07-05 19:14:15 +02:00
Willi Ballenthin
23ed0a5d9d main: don't leave behind traces of the progress bar 2023-07-05 19:06:33 +02:00
Willi Ballenthin
2b6cc6fee2 changelog 2023-07-05 18:57:37 +02:00
Willi Ballenthin
6a76760033 render: use fancy boxes
closes #1586
2023-07-05 18:55:32 +02:00
Willi Ballenthin
dd2d5431a9 setup: bump networkx to 3.1 since we now have python 3.8 as min version 2023-07-05 18:44:12 +02:00
Willi Ballenthin
5d1e26a95e update minimum supported python version to 3.8 2023-07-05 18:34:41 +02:00
Willi Ballenthin
bf5b2612c8 changelog 2023-07-05 18:27:20 +02:00
Willi Ballenthin
694143ce6b import-to-ida: use Metadata type not json document 2023-07-05 18:24:37 +02:00
Willi Ballenthin
19a5ef8a64 import-to-ida: use existing result document json parser 2023-07-05 18:21:03 +02:00
Willi Ballenthin
169b3d60a8 import-to-ida: update to use v5 JSON format
closes #1584
2023-07-05 18:04:15 +02:00
Willi Ballenthin
bb053561ef import-to-ida: decode MD5 to hex 2023-07-05 18:03:57 +02:00
Yacine Elhamer
9ffe85fd9c build_statements: add support for scope flavors 2023-07-05 15:57:57 +01:00
Yacine Elhamer
8ba86e9cea add update Scopes class and switch scope to scopes 2023-07-05 15:00:14 +01:00
Moritz
b1eda6c24d Merge pull request #1568 from mandiant/update-lint-data
update att&ck/mbc data via script
2023-07-05 13:11:22 +02:00
mr-tz
1a2e034ee0 update data via script 2023-07-05 12:30:54 +02:00
Capa Bot
a6763d8882 Sync capa rules submodule 2023-07-05 08:59:18 +00:00
Capa Bot
16ce6a5ef2 Sync capa rules submodule 2023-07-05 08:57:27 +00:00
Capa Bot
0a74eb671f Sync capa rules submodule 2023-07-05 06:58:23 +00:00
Capa Bot
0c3c5e42ff Sync capa rules submodule 2023-07-05 06:41:40 +00:00
Capa Bot
1e258c3bc2 Sync capa rules submodule 2023-07-05 06:41:20 +00:00
Capa Bot
2d55976cb4 Sync capa rules submodule 2023-07-05 06:40:30 +00:00
Capa Bot
9a7ce0b048 Sync capa-testfiles submodule 2023-07-04 08:55:21 +00:00
Capa Bot
446114acc3 Sync capa-testfiles submodule 2023-07-04 08:54:56 +00:00
Capa Bot
30950f129e Sync capa-testfiles submodule 2023-07-04 08:54:40 +00:00
Yacine Elhamer
c042a28af1 rename Flavor to Scopes 2023-07-03 19:21:08 +01:00
Capa Bot
066e42e271 Sync capa-testfiles submodule 2023-07-03 14:05:29 +00:00
Capa Bot
301d8425c1 Sync capa-testfiles submodule 2023-07-03 14:05:01 +00:00
Capa Bot
165fe87aca Sync capa-testfiles submodule 2023-07-03 14:04:39 +00:00
Yacine Elhamer
1b59efc79a Apply suggestions from code review: rename Flavor to Scopes
Co-authored-by: Willi Ballenthin (Google) <118457858+wballenthin@users.noreply.github.com>
2023-07-03 11:11:14 +01:00
Capa Bot
06dd6f45c0 Sync capa rules submodule 2023-07-03 07:54:42 +00:00
Yacine Elhamer
f1d7ac36eb Update test_rules.py 2023-07-03 02:48:24 +01:00
Yacine Elhamer
21cecb2aec tests: add unit tests for flavored scopes 2023-07-01 01:51:44 +01:00
Yacine Elhamer
8a93a06b71 fix mypy issues 2023-07-01 01:41:19 +01:00
Yacine Elhamer
d2ff0af34a Revert "tests: add unit tests for flavored scopes"
This reverts commit 6f0566581e.
2023-07-01 01:39:54 +01:00
Yacine Elhamer
ae5f2ec104 fix mypy issues 2023-07-01 01:38:37 +01:00
Yacine Elhamer
6f0566581e tests: add unit tests for flavored scopes 2023-07-01 00:57:01 +01:00
Yacine Elhamer
e726c7894c ensure_feature_valid_for_scope(): add support for flavored scopes 2023-07-01 00:56:35 +01:00
Yacine Elhamer
c4bb4d9508 update changelog 2023-06-30 20:28:40 +01:00
Yacine Elhamer
cfad228d3c scope flavors: add a Flavor class 2023-06-30 20:26:55 +01:00
Capa Bot
2cd6b8bdac Sync capa-testfiles submodule 2023-06-29 10:01:38 +00:00
Capa Bot
7ab2a9b163 Sync capa-testfiles submodule 2023-06-29 09:47:46 +00:00
Willi Ballenthin
670faf1d1d Merge pull request #1576 from yelhamer/process-scope 2023-06-28 16:34:15 +02:00
Yacine Elhamer
659163a93c thread scope: fix feature inheritance error 2023-06-28 14:52:00 +01:00
Yacine Elhamer
2b163edc0e add thread scope 2023-06-28 13:08:11 +01:00
Yacine Elhamer
0d38f85db7 process scope: add MatchedRule feature 2023-06-28 11:27:08 +01:00
Willi Ballenthin
1dc2825a75 Merge pull request #1577 from mandiant/master
sync dynamic-feature-extraction
2023-06-28 11:16:01 +02:00
Willi Ballenthin
630e2d23c9 Merge pull request #1569 from yelhamer/static-extractor
add a StaticFeatureExtractor class
2023-06-28 11:13:46 +02:00
Yacine Elhamer
c73187e7d4 Update capa/rules/__init__.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-28 10:08:29 +01:00
Capa Bot
4548303a0c Sync capa rules submodule 2023-06-28 06:25:24 +00:00
Yacine Elhamer
e18afe5d1e Merge branch 'dynamic-feature-extraction' into process-scope 2023-06-28 01:46:39 +01:00
Yacine Elhamer
7534e3f739 update changelog 2023-06-28 01:41:13 +01:00
Yacine Elhamer
0e01d91cec update changelog 2023-06-28 01:39:11 +01:00
Aayush Goel
4ceff605bf Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1534 2023-06-27 18:06:57 +05:30
Yacine Elhamer
06aea6b97c fix mypy and codestyle issues 2023-06-27 11:32:21 +01:00
Yacine Elhamer
a99ff813cb DynamicFeatureExtractor: remove get_base_address() method
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-27 11:22:35 +01:00
Yacine Elhamer
92734416a6 update base_extractor.py example
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-27 11:20:41 +01:00
Yacine Elhamer
2f32d4fe49 Update base_extractor.py with review comments
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-27 11:20:02 +01:00
Willi Ballenthin
81d35eb645 Merge branch 'dynamic-feature-extraction' into static-extractor 2023-06-27 09:42:16 +02:00
Willi Ballenthin
ac24ac2507 Merge pull request #1566 from yelhamer/dynamic-show-features
integrate the CAPE extractor with the show-features.py script
2023-06-27 09:37:27 +02:00
Willi Ballenthin
39bb4ed842 Merge pull request #1570 from mandiant/dependabot/pip/ruff-0.0.275
build(deps-dev): bump ruff from 0.0.270 to 0.0.275
2023-06-27 09:34:23 +02:00
dependabot[bot]
8edeb0e6e8 build(deps-dev): bump ruff from 0.0.270 to 0.0.275
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.270 to 0.0.275.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.270...v0.0.275)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-27 07:33:03 +00:00
Willi Ballenthin
e3b58eac67 Merge pull request #1573 from mandiant/dependabot/pip/mypy-1.4.1
build(deps-dev): bump mypy from 1.3.0 to 1.4.1
2023-06-27 09:32:25 +02:00
Willi Ballenthin
8b23a86d2e Merge branch 'master' into dependabot/pip/mypy-1.4.1 2023-06-27 09:32:14 +02:00
Willi Ballenthin
d95acc9734 Merge pull request #1574 from mandiant/dependabot/pip/pytest-7.4.0
build(deps-dev): bump pytest from 7.3.1 to 7.4.0
2023-06-27 09:32:03 +02:00
Yacine Elhamer
b172f9a354 FeatureExtractor alias: fix mypy typing issues by adding ininstance-based assert statements 2023-06-26 22:46:27 +01:00
Yacine Elhamer
63e4d3d5eb fix TypeAlias importing: import from typing_extensions to support Python 3.9 and lower 2023-06-26 21:14:17 +01:00
Yacine Elhamer
c74c8871f8 scripts: add type-related assert statements 2023-06-26 21:06:35 +01:00
Yacine Elhamer
3f5d08aedb base_extractor.py: add TypeAlias keyword, use union instead of bar operator, add an extract_file_features() and extract_global_features() methods 2023-06-26 20:57:51 +01:00
Yacine Elhamer
ddcb299834 main.py: address review suggestions (using elif for type casts, renaming to find_static_capabilities()) 2023-06-26 20:53:41 +01:00
Yacine Elhamer
a9f70dd1e5 main.py: update extractor type casting
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-26 20:01:30 +01:00
dependabot[bot]
7c72b56a4e build(deps-dev): bump pytest from 7.3.1 to 7.4.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.3.1 to 7.4.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.3.1...7.4.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 14:58:39 +00:00
dependabot[bot]
8429d6b8e2 build(deps-dev): bump mypy from 1.3.0 to 1.4.1
Bumps [mypy](https://github.com/python/mypy) from 1.3.0 to 1.4.1.
- [Commits](https://github.com/python/mypy/compare/v1.3.0...v1.4.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 14:58:26 +00:00
Yacine Elhamer
aff0c6b49b show-featurex.py: bugfix in ida_main() 2023-06-26 09:41:14 +01:00
Yacine Elhamer
417bb42ac8 show_features.py: rename show_{function,process}_features to show_{static,dynamic}_features.py 2023-06-26 09:16:59 +01:00
Yacine Elhamer
040ed4fa57 get_format_from_report(): use strings instead of literals
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-26 09:05:20 +01:00
Yacine Elhamer
94fc7b4e9a FeatureExtractor alias: add type casts to either StaticFeatureExtractor or DynamicFeatureExtractor 2023-06-26 01:23:01 +01:00
Yacine Elhamer
172e7a7649 update changelog 2023-06-25 23:03:13 +01:00
Yacine Elhamer
37ed138dcf base_extractor(): add a StaticFeatureExtractor and DynamicFeatureExtractor base classes, as well as a FeatureExtractor type alias 2023-06-25 22:57:39 +01:00
Aayush Goel
842f76c8bd Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1534 2023-06-26 00:35:55 +05:30
Aayush Goel
157dfac527 Current os.apth to pathlib.Path
need to update args type

Revert "Current os.apth to pathlib.Path"

This reverts commit 170fe9ad93b0a4d44a08470633133c0d32ccef24.
2023-06-26 00:34:12 +05:30
Yacine Elhamer
5f6aade92b get_format_from_report(): fix bugs and add a list of dynamic formats 2023-06-25 00:54:55 +01:00
Yacine Elhamer
0c62a5736e add support for determining the format of a sandbox report 2023-06-24 23:51:12 +01:00
Capa Bot
a92d91e82a Sync capa rules submodule 2023-06-24 08:21:24 +00:00
Yacine Elhamer
f1406c1ffd scripts/show-features.py: prefix {static,dynamic}_analysis() functions' name with 'print_' 2023-06-23 13:58:34 +01:00
Yacine Elhamer
1cdc3e5232 fix codestyle 2023-06-23 13:48:49 +01:00
Yacine Elhamer
bd9870254e Apply suggestions from code review: use EXTENSIONS_CAPE, and ident 'thread' by one more space 2023-06-23 13:31:35 +01:00
Yacine Elhamer
0442b8c1e1 Apply suggestions from code review: use is_ for booleans
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-23 13:27:20 +01:00
Yacine Elhamer
585876d6af capa/main.py: use "rb" for opening json files
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-23 13:25:37 +01:00
Yacine Elhamer
902d726ea6 capa/main.py: change json import positioning to start of the file 2023-06-22 23:57:03 +01:00
Yacine Elhamer
3f35b426dd Apply suggestions from code review
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-22 21:58:01 +01:00
Yacine Elhamer
761d861888 Update fixtures.py samples path 2023-06-22 16:55:00 +01:00
Yacine Elhamer
9f185ed5c0 remove incompatible bar union syntax 2023-06-22 15:59:23 +01:00
Yacine Elhamer
63b2077335 get_extractor(): set return type to FeatureExtractor, and cast into the appropriate class before each usage 2023-06-22 15:55:24 +01:00
Yacine Elhamer
12d5beec6e add type cast to fix get_extractor() typing issues 2023-06-22 15:51:56 +01:00
Yacine Elhamer
b77e68df19 fix codestyle and typing 2023-06-22 14:17:06 +01:00
Yacine Elhamer
fcdd4fa410 update changelog 2023-06-22 14:03:01 +01:00
Yacine Elhamer
07c48bca68 scripts/show-features.py: add dynamic feature extraction from cape reports 2023-06-22 13:56:54 +01:00
Yacine Elhamer
79ff76d124 main.py: fix bugs for adding the cape extractor/format 2023-06-22 13:55:50 +01:00
Yacine Elhamer
de2ba1ca94 add the cape report format to main and across several other locations 2023-06-22 12:55:39 +01:00
Yacine Elhamer
45002bd51d Revert "scripts/show-features.py: add dynamic feature extraction from cape reports"
This reverts commit 64189a4d08.
2023-06-22 12:29:51 +01:00
Yacine Elhamer
be7ebad956 Revert "tests/fixtures.py: update path forming for the cape sample"
This reverts commit 6712801b01.
2023-06-22 12:18:34 +01:00
Yacine Elhamer
64189a4d08 scripts/show-features.py: add dynamic feature extraction from cape reports 2023-06-22 12:16:31 +01:00
Capa Bot
33a3170bc4 Sync capa rules submodule 2023-06-22 07:11:54 +00:00
Willi Ballenthin
708cb28ed0 Merge pull request #1546 from yelhamer/cape-extractor
add the CAPE feature extractor
2023-06-21 09:33:26 +02:00
Yacine Elhamer
6712801b01 tests/fixtures.py: update path forming for the cape sample
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-20 20:30:06 +01:00
Yacine Elhamer
f29db693c8 fix git submodules error 2023-06-20 20:25:19 +01:00
Yacine Elhamer
0502bfd95d remove cape report from get_md5_hash() function 2023-06-20 20:24:38 +01:00
Yacine Elhamer
78a3901c61 cape/helpers.py: add a find_process() function for quick-fetching processes from the cape report 2023-06-20 15:59:22 +01:00
Yacine Elhamer
0a4e3008af fixtures.py: update CAPE's feature count and presence tests 2023-06-20 13:51:16 +01:00
Willi Ballenthin
2ce4f8769d Merge pull request #1513 from mandiant/ida-test-runner
tests: refine the IDA test runner
2023-06-20 14:28:12 +02:00
Willi Ballenthin
4dedc24f9f Merge branch 'master' into ida-test-runner 2023-06-20 14:28:05 +02:00
Yacine Elhamer
d03ba5394f cape/global_.py: add warning messages if architecture/os/format are unknown 2023-06-20 13:26:25 +01:00
Yacine Elhamer
2262e6c7d0 Merge branch 'test-cape-extractor' into cape-extractor 2023-06-20 13:22:15 +01:00
Yacine Elhamer
31a349b13b cape feature tests: fix feature count function typo 2023-06-20 13:21:52 +01:00
Yacine Elhamer
1ba143ef26 Merge branch 'test-cape-extractor' into cape-extractor 2023-06-20 13:20:49 +01:00
Yacine Elhamer
1532ce1bab add tests for extracting argument values 2023-06-20 13:20:33 +01:00
Yacine Elhamer
fa9b920b71 cape/thread.py: do not extract return values, and extract argument values as Strings 2023-06-20 13:17:53 +01:00
Yacine Elhamer
40b2d5f724 add a remote origin to submodule, and switch to that branch 2023-06-20 12:40:47 +01:00
Yacine Elhamer
0623a5a8de point capa-testfiles submodule towards dynamic-feautre-extractor branch 2023-06-20 12:13:57 +01:00
Yacine Elhamer
cfa1d08e7e update testfiles submodule to point at dev branch 2023-06-20 11:28:40 +01:00
Yacine Elhamer
6196814672 cape/file.py: fix KeyError bug 2023-06-20 10:51:18 +01:00
Yacine Elhamer
f5af2bf393 Merge branch 'test-cape-extractor' into cape-extractor 2023-06-20 10:47:56 +01:00
Yacine Elhamer
374fb033c1 add support for gzip compressed cape samples, and fix QakBot sample path 2023-06-20 10:29:52 +01:00
Yacine Elhamer
4db80e75a4 add mode and encoding parameters to open() 2023-06-20 10:13:06 +01:00
Yacine Elhamer
8547277958 tests/fixtures.py bugfix: remove redundant lambda function
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-20 10:10:42 +01:00
Yacine Elhamer
ec3366b0e5 Update tests/fixtures.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-20 10:09:27 +01:00
Yacine Elhamer
48bd04b387 tests/fixtures.py: return direct extractor with no intermediate variable
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-20 10:09:00 +01:00
Yacine Elhamer
41a481252c Update CHANGELOG.md
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-20 10:08:12 +01:00
Yacine Elhamer
a7cf3b5b10 features/insn.py: revert added strace-based API feature 2023-06-20 10:04:37 +01:00
Yacine Elhamer
ba63188f27 cape/file.py: fix bug in call to helpers.generate_symbols()
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-20 10:02:57 +01:00
Yacine Elhamer
9cc34cb70f cape/file.py: fix imports ordering and format 2023-06-20 00:19:55 +01:00
Yacine Elhamer
b9a4d72b42 cape/file.py: add usage of helpers.generate_symbols() 2023-06-20 00:12:21 +01:00
Yacine Elhamer
8eef210547 update changelog 2023-06-19 23:57:51 +01:00
Yacine Elhamer
ef999ed954 rules/__init__.py: remove redundant HBI features 2023-06-19 23:56:10 +01:00
Yacine Elhamer
33de609560 Revert "removed redundant HBI features"
This reverts commit c88f859dae.
2023-06-19 23:55:22 +01:00
Yacine Elhamer
624151c3f7 Revert "update changelog"
This reverts commit 49b77d5477.
2023-06-19 23:55:12 +01:00
Yacine Elhamer
c88f859dae removed redundant HBI features 2023-06-19 23:55:06 +01:00
Yacine Elhamer
49b77d5477 update changelog 2023-06-19 23:49:19 +01:00
Yacine Elhamer
d4c4a17eb7 bugfixes and add cape sample tests 2023-06-19 23:42:27 +01:00
Yacine Elhamer
3c8abab574 fix bugs and refactor code 2023-06-19 23:40:09 +01:00
Yacine Elhamer
38596f8d0e add features for the QakBot sample 2023-06-19 19:32:56 +01:00
Yacine Elhamer
4acdca090d bug fixes 2023-06-19 17:14:59 +01:00
Yacine Elhamer
f02178852b update changelog 2023-06-19 17:01:05 +01:00
Yacine Elhamer
98e7acddf4 fix codestyle issues 2023-06-19 16:59:27 +01:00
Yacine Elhamer
9458e851c0 update test sample's path 2023-06-19 16:46:24 +01:00
Yacine Elhamer
a04512d7b8 add unit tests for the cape feature extractor 2023-06-19 16:43:54 +01:00
Moritz
1bc0174f6f Merge pull request #1562 from mandiant/dependabot/pip/ruamel-yaml-0.17.32
build(deps): bump ruamel-yaml from 0.17.28 to 0.17.32
2023-06-19 17:24:22 +02:00
Moritz
90842f313a Merge pull request #1543 from mandiant/dependabot/pip/pydantic-1.10.9
build(deps): bump pydantic from 1.10.7 to 1.10.9
2023-06-19 17:23:51 +02:00
Moritz
6aa2f6457c Merge pull request #1521 from mandiant/dependabot/pip/pytest-cov-4.1.0
build(deps-dev): bump pytest-cov from 4.0.0 to 4.1.0
2023-06-19 17:23:19 +02:00
Moritz
b7c600e60b Merge pull request #1520 from mandiant/dependabot/pip/requests-2.31.0
build(deps-dev): bump requests from 2.28.0 to 2.31.0
2023-06-19 17:22:55 +02:00
Moritz
d397b46b63 Merge pull request #1518 from mandiant/dependabot/pip/types-requests-2.31.0.1
build(deps-dev): bump types-requests from 2.28.1 to 2.31.0.1
2023-06-19 17:22:32 +02:00
dependabot[bot]
7a6b7c5ef0 build(deps): bump ruamel-yaml from 0.17.28 to 0.17.32
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.28 to 0.17.32.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 14:58:25 +00:00
Yacine Elhamer
d6fa832d83 cape: move get_processes() method to file scope 2023-06-19 13:50:46 +01:00
Yacine Elhamer
dbad921fa5 code style changes 2023-06-15 13:21:17 +01:00
Yacine Elhamer
e1535dd574 remove Registry, Filename, and mutex features 2023-06-15 13:17:07 +01:00
Yacine Elhamer
22640eb900 cape/file.py: remove FunctionName feature extraction for imported functions 2023-06-15 12:44:57 +01:00
Yacine Elhamer
7e51e03043 cape/file.py: remove String, Filename, and Mutex features 2023-06-15 12:43:39 +01:00
Yacine Elhamer
865616284f cape/thread.py: remove yielding argument features
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-15 12:33:22 +01:00
Yacine Elhamer
0cf728b7e1 global_.py: update typo in yielded OS name
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-15 12:28:08 +01:00
Willi Ballenthin
a2d563b081 Merge branch 'dynamic-feature-extraction' into cape-extractor 2023-06-15 12:43:55 +02:00
Willi Ballenthin
8119aa6933 ci: do tests on dynamic-feature-extraction branch 2023-06-15 12:17:02 +02:00
Willi Ballenthin
6b953363d1 Update capa/features/extractors/base_extractor.py 2023-06-15 11:40:33 +02:00
Willi Ballenthin
139b240250 Update capa/features/extractors/base_extractor.py 2023-06-15 11:40:32 +02:00
Willi Ballenthin
36b5dff1f0 Update capa/features/extractors/base_extractor.py 2023-06-15 11:40:32 +02:00
Yacine Elhamer
7ae07d4de5 remove redundant types
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-15 11:40:32 +02:00
Yacine Elhamer
59ef52a271 remove default implementation
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-15 11:40:31 +02:00
Yacine Elhamer
34a1b22a38 remove ppid member from ProcessHandle
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-15 11:40:31 +02:00
Yacine Elhamer
b4f01fa6c2 add ppid documentation to the dynamic extractor interface 2023-06-15 11:40:30 +02:00
Yacine Elhamer
2d6d16dcd0 add parent process id to the process handle 2023-06-15 11:40:30 +02:00
Yacine Elhamer
1ccae4fef2 remove from_trace() and submit_sample() methods 2023-06-15 11:40:29 +02:00
Yacine Elhamer
ee30acab32 get_threads(): fix mypy typing
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-15 11:40:29 +02:00
Yacine Elhamer
5189bef325 fix bad comment
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-15 11:40:28 +02:00
Yacine Elhamer
17597580f4 add abstract DynamicExtractor class 2023-06-15 11:40:28 +02:00
Yacine Elhamer
f97f9e8646 Merge branch 'dynamic-features' into cape-extractor 2023-06-14 23:07:39 +01:00
Yacine Elhamer
91f1d41324 extract registry keys, files, and mutexes from the sample 2023-06-14 22:57:41 +01:00
Yacine Elhamer
d9d9d98ea0 update the Registry, Filename, and Mutex classes 2023-06-14 22:45:12 +01:00
Willi Ballenthin
e7115c7316 Update capa/features/extractors/base_extractor.py 2023-06-14 22:43:37 +01:00
Willi Ballenthin
6c58e26f14 Update capa/features/extractors/base_extractor.py 2023-06-14 22:43:37 +01:00
Willi Ballenthin
dc371580a5 Update capa/features/extractors/base_extractor.py 2023-06-14 22:43:37 +01:00
Yacine Elhamer
2a047073e9 remove redundant types
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-14 22:43:37 +01:00
Stephen Eckels
6e3b1bc240 explorer: optimize cache and extractor interface (#1470)
* Optimize cache and extractor interface

* Update changelog

* Run linter formatters

* Implement review feedback

* Move rulegen extractor construction to tab change

* Change rulegen cache construction behavior

* Adjust return values for CR, format

* Fix mypy errors

* Format

* Fix merge

---------

Co-authored-by: Stephen Eckels <stephen.eckels@mandiant.com>
2023-06-14 22:43:37 +01:00
Capa Bot
51faaae1d0 Sync capa rules submodule 2023-06-14 22:43:37 +01:00
Capa Bot
f55804ef06 Sync capa rules submodule 2023-06-14 22:43:37 +01:00
Xusheng
e671e1c87c Add a test that asserts on the binja version 2023-06-14 22:43:37 +01:00
Xusheng
a7aa817dce Update the stack string detection with BN's builtin outlining of constant expressions 2023-06-14 22:43:37 +01:00
Capa Bot
dcce4db6d5 Sync capa rules submodule 2023-06-14 22:43:37 +01:00
Yacine Elhamer
64c4f0f1aa remove default implementation
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-14 22:43:37 +01:00
Yacine Elhamer
a8f928200b remove ppid member from ProcessHandle
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-14 22:43:37 +01:00
Yacine Elhamer
58d42b09d9 add ppid documentation to the dynamic extractor interface 2023-06-14 22:43:37 +01:00
Yacine Elhamer
0cd481b149 remove redundant comments
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-14 22:42:25 +01:00
Yacine Elhamer
a66c55ca14 add the initial version of the cape extractor 2023-06-14 22:34:11 +01:00
Yacine Elhamer
18715dbe2e fix typo bug 2023-06-14 21:47:40 +01:00
Willi Ballenthin
23dee61389 Merge branch 'dynamic-feature-extraction' into cape-extractor 2023-06-14 12:41:08 +02:00
Willi Ballenthin
23dc3f29cd Merge pull request #1528 from yelhamer/dynamic-extractor
add a Dynamic extractor interface
2023-06-14 11:00:06 +02:00
Willi Ballenthin
4c701f4b6c Update capa/features/extractors/base_extractor.py 2023-06-14 10:59:07 +02:00
Willi Ballenthin
7a94f524b4 Update capa/features/extractors/base_extractor.py 2023-06-14 10:58:59 +02:00
Willi Ballenthin
23deb41436 Update capa/features/extractors/base_extractor.py 2023-06-14 10:58:50 +02:00
Yacine Elhamer
7198ebefc9 remove redundant types
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-14 09:58:33 +01:00
Willi Ballenthin
32cb57532e Merge branch 'dynamic-feature-extraction' into dynamic-extractor 2023-06-14 10:54:44 +02:00
Yacine Elhamer
edcfece993 remove default implementation
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-14 09:33:24 +01:00
Yacine Elhamer
baf209f3cc remove ppid member from ProcessHandle
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-14 09:33:07 +01:00
Yacine Elhamer
ece47c9ed5 add ppid documentation to the dynamic extractor interface 2023-06-14 09:05:53 +01:00
Yacine Elhamer
3d40ed968a Merge branch 'dynamic-features' into cape-extractor 2023-06-13 23:04:44 +01:00
Yacine Elhamer
10f56de5e8 Merge branch 'dynamic-extractor' into dynamic-features 2023-06-13 23:03:33 +01:00
Yacine Elhamer
5ee4fc2cd5 add parent process id to the process handle 2023-06-13 23:02:00 +01:00
Yacine Elhamer
a7917a0f3d add cape's thread features' extraction module 2023-06-13 22:56:15 +01:00
Yacine Elhamer
0274cf3ec7 add cape's global features' extraction module 2023-06-13 22:55:42 +01:00
Yacine Elhamer
3aa7c96902 add cape extractor class 2023-06-13 22:54:52 +01:00
Stephen Eckels
7ef78fdbce explorer: optimize cache and extractor interface (#1470)
* Optimize cache and extractor interface

* Update changelog

* Run linter formatters

* Implement review feedback

* Move rulegen extractor construction to tab change

* Change rulegen cache construction behavior

* Adjust return values for CR, format

* Fix mypy errors

* Format

* Fix merge

---------

Co-authored-by: Stephen Eckels <stephen.eckels@mandiant.com>
2023-06-13 12:00:06 -06:00
Yacine Elhamer
ffa1851bbf Merge branch 'dynamic-features' into cape-extractor 2023-06-13 14:26:34 +01:00
Yacine Elhamer
45c3345bbc Merge branch 'dynamic-extractor' into dynamic-features 2023-06-13 14:26:14 +01:00
Yacine Elhamer
a6ca3aaa66 remove from_trace() and submit_sample() methods 2023-06-13 14:23:50 +01:00
dependabot[bot]
366c55231e build(deps): bump pydantic from 1.10.7 to 1.10.9
Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.10.7 to 1.10.9.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v1.10.7...v1.10.9)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 14:58:23 +00:00
Capa Bot
43b2ee3c52 Sync capa rules submodule 2023-06-12 12:28:18 +00:00
Capa Bot
85a7c87830 Sync capa rules submodule 2023-06-12 12:18:23 +00:00
Willi Ballenthin
2d7e20f532 Merge pull request #1527 from xusheng6/fix_bn_unit_test
Update the stack string detection with BN's builtin outlining of constant expressionss
2023-06-12 10:41:15 +02:00
Capa Bot
cc993b67a3 Sync capa rules submodule 2023-06-12 06:58:29 +00:00
Yacine Elhamer
5a10b612a1 add a Mutex feature 2023-06-12 00:06:53 +01:00
Yacine Elhamer
632b3ff07c add a Filename feature 2023-06-12 00:06:05 +01:00
Yacine Elhamer
efe1d1c0ac add a Registry feature 2023-06-12 00:05:20 +01:00
Yacine Elhamer
86e2f83a7d extend the API feature to support an strace-like argument style 2023-06-11 23:19:24 +01:00
Yacine Elhamer
a2b3a38f86 add the cape extractor's file hierarchy 2023-06-10 20:06:57 +01:00
Yacine Elhamer
f243749d38 get_threads(): fix mypy typing
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-09 09:03:49 +00:00
Yacine Elhamer
dac103c621 fix bad comment
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-06-09 09:03:09 +00:00
Xusheng
a74911e926 Add a test that asserts on the binja version 2023-06-09 13:44:07 +08:00
Xusheng
8cc16e8de9 Update the stack string detection with BN's builtin outlining of constant expressions 2023-06-09 13:41:53 +08:00
Yacine Elhamer
35e53e9691 add abstract DynamicExtractor class 2023-06-08 23:15:29 +00:00
Capa Bot
0559e61af1 Sync capa rules submodule 2023-06-08 08:41:14 +00:00
colton-gabertan
3da233dcad colton: removed redundant imports & object, locally tested 2023-06-07 13:04:49 -07:00
Capa Bot
2fe0713faa Sync capa rules submodule 2023-06-07 10:17:28 +00:00
Willi Ballenthin
28629b352c Merge pull request #1502 from Aayush-Goel-04/Aayush-Goel-04/Issue#1411
Update Metadata type in capa main
2023-06-06 13:04:35 +02:00
Aayush Goel
e5f79c9f5c Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1411 2023-06-06 13:04:19 +05:30
Aayush Goel
c6815ef126 Update Model and FrozenModel Class 2023-06-06 13:02:30 +05:30
dependabot[bot]
28b2cd5117 build(deps-dev): bump pytest-cov from 4.0.0 to 4.1.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 4.0.0 to 4.1.0.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-05 14:58:21 +00:00
dependabot[bot]
28c24c9d48 build(deps-dev): bump requests from 2.28.0 to 2.31.0
Bumps [requests](https://github.com/psf/requests) from 2.28.0 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.28.0...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-05 14:58:17 +00:00
dependabot[bot]
b2080cdfbc build(deps-dev): bump types-requests from 2.28.1 to 2.31.0.1
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.1 to 2.31.0.1.
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-05 14:58:02 +00:00
Willi Ballenthin
57095175d2 Merge pull request #1443 from yelhamer/feature-static-api-names
Extract api names from ELF debug symbols [vivisect]
2023-06-05 14:54:34 +02:00
Yacine Elhamer
5b260c00f4 fix symtab FunctionName feature scope address 2023-06-05 13:37:19 +01:00
Yacine Elhamer
9b0fb74d94 fix typo: "Elf" to "elf" 2023-06-05 13:36:50 +01:00
Yacine Elhamer
103b384c09 fix viv/extractor.py codestyle imports 2023-06-05 12:17:27 +01:00
Yacine Elhamer
65f18aecc8 fix mypy typing issues 2023-06-05 12:14:56 +01:00
Yacine Elhamer
e971bc4044 fix codestyle issues 2023-06-05 12:01:39 +01:00
Aayush Goel
b4870b120e Remove from_capa API for MetaData 2023-06-03 15:33:49 +05:30
Colton Gabertan
a7988a6e78 Merge pull request #1514 from colton-gabertan/master
New Feature: Ghidra Backend - Initial Merge
2023-06-02 23:40:23 -07:00
Colton Gabertan
de19c9300d Merge pull request #1 from colton-gabertan/ghidra_backend
Ghidra backend
2023-06-02 23:24:43 -07:00
colton-gabertan
a7639d33b9 colton: update CHANGELOG 2023-06-02 23:11:18 -07:00
Colton Gabertan
c3f9c27e34 Merge branch 'mandiant:master' into ghidra_backend 2023-06-02 22:42:35 -07:00
colton-gabertan
b849cfd4a5 ghidra ci setup, test files in development 2023-06-02 22:41:29 -07:00
Yacine Elhamer
7dff76b122 Merge branch 'master' into feature-static-api-names 2023-06-03 01:44:13 +01:00
Yacine Elhamer
be5ada26ea fix code style 2023-06-03 01:12:56 +01:00
Yacine Elhamer
5b903ca4f3 add error handling to SymTab and its callers 2023-06-02 23:19:14 +01:00
Yacine Elhamer
6b2710ac7e fix broken logic in extract_function_symtab_names() 2023-06-02 22:43:58 +01:00
Yacine Elhamer
764fda8e7b add missing Shdr.from_viv() method 2023-06-02 17:57:37 +01:00
Yacine Elhamer
151ef95b79 remove usage of vsGetField 2023-06-02 17:14:44 +01:00
Yacine Elhamer
4976375d74 elf.py: fix identation error 2023-06-02 16:30:17 +01:00
Yacine Elhamer
0b834a1623 delete functionName extraction at instruction level
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-02 15:56:14 +01:00
Yacine Elhamer
41c512624b update symtab-based FunctionName feature extraction 2023-06-02 14:44:51 +01:00
Yacine Elhamer
9467ee6f10 add FunctionName extraction at the function scope 2023-06-02 14:42:04 +01:00
Yacine Elhamer
dde76e301d add a method to construct SymTab objects from Elf objects 2023-06-02 12:15:05 +01:00
Aayush Goel
5ded85f46e Update CHANGELOG.md 2023-06-02 14:54:36 +05:30
Capa Bot
0cbe4618e1 Sync capa-testfiles submodule 2023-06-02 09:20:23 +00:00
Aayush Goel
f03ad2d208 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1411 2023-06-02 14:47:24 +05:30
Willi Ballenthin
8b867836e9 changelog 2023-06-02 10:45:05 +02:00
Willi Ballenthin
236c1c9d17 tests: refine the IDA test runner
ref #1364
2023-06-02 10:40:47 +02:00
Willi Ballenthin
64dca7d801 Merge branch 'master' into feature-static-api-names 2023-06-02 09:26:25 +02:00
Willi Ballenthin
3834314c2a Merge pull request #1463 from Aayush-Goel-04/Aayush-Goel-04/Issue#1451
Utility script to detect feature overlap between new and existing CAPA rules.
2023-06-02 09:18:00 +02:00
Willi Ballenthin
144723be3c Merge pull request #1496 from mandiant/dependabot/pip/ruamel-yaml-0.17.28
build(deps): bump ruamel-yaml from 0.17.21 to 0.17.28
2023-06-02 09:16:29 +02:00
Capa Bot
0f54a6f67e Sync capa rules submodule 2023-06-02 07:13:58 +00:00
Yacine Elhamer
1cec768521 fix strtab renaming error 2023-06-01 22:20:23 +01:00
Yacine Elhamer
d85d01eea1 use the function-handle's cache instead of the VivWorkspace file metadata 2023-06-01 22:15:47 +01:00
Yacine Elhamer
8d1e1cc54c fix strtab naming 2023-06-01 21:56:34 +01:00
Aayush Goel
0d9e74028e Update Metadata 2023-06-02 01:19:42 +05:30
Aayush Goel
445214b23b Update Metadata type in capa main 2023-06-02 00:40:38 +05:30
colton-gabertan
16444fe5ed first working CI install 2023-06-01 11:24:21 -07:00
Yacine Elhamer
994edf66fe return the target's address for the function-name feature 2023-06-01 12:45:49 +01:00
Yacine Elhamer
f9291d4e50 extract symtab-api names before processing library functions 2023-06-01 12:45:10 +01:00
Yacine Elhamer
ab089c024d fetch section data by offset (not name)
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-01 11:46:39 +01:00
Yacine Elhamer
ffb1cb3128 rename strtab to strtab_section
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-01 10:26:40 +01:00
Yacine Elhamer
57386812f9 use ELF class member instead of vsGetField()
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-06-01 10:26:21 +01:00
Willi Ballenthin
ce8e15a220 Merge branch 'master' into feature-static-api-names 2023-06-01 09:39:07 +02:00
Yacine Elhamer
0d42ac3912 add missing function-name feature testing 2023-06-01 02:14:25 +01:00
Yacine Elhamer
f10a43abe6 fix style issues 2023-06-01 02:02:40 +01:00
Yacine Elhamer
64ef2c8a65 add tests for vivisect's usage of debug symbols 2023-06-01 01:50:06 +01:00
Capa Bot
d3c44a8263 Sync capa rules submodule 2023-05-31 18:16:12 +00:00
Moritz
8d016de217 Merge pull request #1494 from mandiant/dependabot/pip/protobuf-4.23.2
build(deps): bump protobuf from 4.22.3 to 4.23.2
2023-05-31 07:54:15 +02:00
Moritz
ee3d3a964e Merge pull request #1483 from mandiant/dependabot/pip/types-protobuf-4.23.0.1
build(deps-dev): bump types-protobuf from 4.22.0.2 to 4.23.0.1
2023-05-31 07:53:53 +02:00
Aayush Goel
d6e145936d Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1451 2023-05-31 00:26:48 +05:30
Capa Bot
9caea57cde Sync capa rules submodule 2023-05-30 14:37:56 +00:00
Capa Bot
99e81e1d8f Sync capa rules submodule 2023-05-30 14:31:43 +00:00
Capa Bot
1696a9ad2d Sync capa-testfiles submodule 2023-05-30 14:28:43 +00:00
Willi Ballenthin
6c2a83dda8 Merge pull request #1495 from mandiant/dependabot/pip/ruff-0.0.270
build(deps-dev): bump ruff from 0.0.265 to 0.0.270
2023-05-30 12:02:16 +02:00
colton-gabertan
5af1a42bf1 reverting tests.yml 2023-05-29 20:24:37 -07:00
colton-gabertan
73183e9c19 run tests.yml on workflow dispatch 2023-05-29 20:16:10 -07:00
colton-gabertan
b35cfdaf6a workflow_dispatch - temp 2023-05-29 20:13:35 -07:00
colton-gabertan
8c40e82796 configuring runner for ghidra tests 2023-05-29 19:58:59 -07:00
dependabot[bot]
c113a3b5b8 build(deps): bump ruamel-yaml from 0.17.21 to 0.17.28
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.21 to 0.17.28.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 14:59:13 +00:00
dependabot[bot]
a07b47c845 build(deps-dev): bump ruff from 0.0.265 to 0.0.270
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.265 to 0.0.270.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.265...v0.0.270)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 14:59:02 +00:00
dependabot[bot]
f789e144fd build(deps): bump protobuf from 4.22.3 to 4.23.2
Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 4.22.3 to 4.23.2.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/generate_changelog.py)
- [Commits](https://github.com/protocolbuffers/protobuf/compare/v4.22.3...v4.23.2)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 14:58:10 +00:00
colton-gabertan
78bd5e1e3b colton: tests.yml installs Java, Ghidra, and Ghidrathon 2023-05-28 19:04:31 -07:00
Aayush Goel
2e534a4128 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1451 2023-05-27 14:14:32 +05:30
colton-gabertan
50afc2f9b2 colton: developing ghidra backend tests 2023-05-26 17:51:48 -07:00
Capa Bot
e068ce7bc9 Sync capa rules submodule 2023-05-26 08:34:57 +00:00
Aayush Goel
2daf880e39 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1451 2023-05-25 13:41:30 +05:30
Willi Ballenthin
7897fa9f29 Merge pull request #1493 from Aayush-Goel-04/Aayush-Goel-04/Issue#749
Add logging redirect to capa main
2023-05-25 09:47:03 +02:00
Aayush Goel
456d4272ab Add logging redirect to capa main 2023-05-25 12:50:42 +05:30
Aayush Goel
52c3ea733b Update tests/test_scripts.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-05-24 15:39:24 +05:30
Aayush Goel
acdaeb26d3 Update test_scripts.py 2023-05-20 13:09:48 +05:30
colton-gabertan
ffe089d444 colton: GhidraFeatureExtractor constructor pulls OS & Arch 2023-05-19 19:10:39 -07:00
colton-gabertan
1f09c92306 colton: OS extraction functionality implemented 2023-05-19 18:38:13 -07:00
colton-gabertan
14b0c5fdbf colton: ghidra runtime detection & GhidraFeatureExtractor 2023-05-19 14:38:55 -07:00
Capa Bot
932066bc0e Sync capa rules submodule 2023-05-19 08:22:32 +00:00
Aayush Goel
66ea0451e9 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1451 2023-05-18 16:30:08 +05:30
Willi Ballenthin
bc05118ee7 Merge pull request #1488 from Aayush-Goel-04/Aayush-Goel-04/Issue#749
Add redirect print to tqdm for capa main
2023-05-18 08:45:45 +02:00
Aayush Goel
275386806d Add redirect print to capa main 2023-05-17 23:57:52 +05:30
Aayush Goel
0afc16fd02 Update test rules to test script 2023-05-17 23:31:37 +05:30
Aayush Goel
6cafe14060 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1451 2023-05-17 12:09:26 +05:30
Willi Ballenthin
ad611c2058 Merge pull request #1480 from Aayush-Goel-04/Aayush-Goel-04/Issue#1446
Create test binja backend when invoking standalone capa.exe
2023-05-16 22:10:10 +02:00
Aayush Goel
b876adbc27 Update CHANGELOG.md 2023-05-16 20:22:54 +05:30
Aayush Goel
e428b74657 run test on PMA 01-01.exe_ 2023-05-16 12:23:00 +05:30
Willi Ballenthin
7ab083f19a Merge pull request #1482 from mandiant/dependabot/pip/mypy-1.3.0
build(deps-dev): bump mypy from 1.2.0 to 1.3.0
2023-05-15 20:54:08 +02:00
Aayush Goel
931dcb1dc5 Update test_scripts.py 2023-05-15 23:35:11 +05:30
Aayush Goel
12c191582f Update tests/test_scripts.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-05-15 22:58:19 +05:30
dependabot[bot]
d861b0798e build(deps-dev): bump types-protobuf from 4.22.0.2 to 4.23.0.1
Bumps [types-protobuf](https://github.com/python/typeshed) from 4.22.0.2 to 4.23.0.1.
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-protobuf
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-15 14:58:08 +00:00
dependabot[bot]
b6e85b878e build(deps-dev): bump mypy from 1.2.0 to 1.3.0
Bumps [mypy](https://github.com/python/mypy) from 1.2.0 to 1.3.0.
- [Commits](https://github.com/python/mypy/compare/v1.2.0...v1.3.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-15 14:58:04 +00:00
Aayush Goel
807efec40f Create RuleSet to test overlap script 2023-05-12 22:44:26 +05:30
Aayush Goel
41ff457d65 Update tests/test_scripts.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-05-12 16:53:44 +05:30
Capa Bot
e605dfb483 Sync capa-testfiles submodule 2023-05-12 08:49:03 +00:00
Aayush Goel
2511f40ab8 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1451 2023-05-12 02:37:15 +05:30
Aayush Goel
61554dbaf0 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1446 2023-05-12 02:36:56 +05:30
Aayush Goel
ce56ab71d4 Update test_binja_features.py
Not sure which file to use to test capa.main
2023-05-12 02:17:09 +05:30
Willi Ballenthin
21c2705827 Merge pull request #1479 from Aayush-Goel-04/Aayush-Goel-04/Issue#1341
Improved layout to exclude functions with no basic block.
2023-05-11 21:40:56 +02:00
Aayush Goel
916db6c197 Update main.py 2023-05-11 19:40:52 +05:30
Aayush Goel
562e03d2d2 Update CHANGELOG.md
Update CHANGELOG.md

Update main.py
2023-05-11 18:59:29 +05:30
Aayush Goel
eca86470c6 Update test_scripts.py
RULE_CONTENT can be modified as required
2023-05-11 14:12:52 +05:30
Capa Bot
a90eda50a7 Sync capa rules submodule 2023-05-11 08:06:38 +00:00
Aayush Goel
187a4712cb Update test_scripts.py
Here new_rule_path and expected_overlaps will be changed based on the new test rule designed.
Adding tests to check if the code works fine
2023-05-10 20:55:22 +05:30
Capa Bot
58bbb8e3a4 Sync capa-testfiles submodule 2023-05-10 14:10:33 +00:00
Willi Ballenthin
d57ed97f9d Merge pull request #1477 from mandiant/dependabot/pip/ruff-0.0.265
build(deps-dev): bump ruff from 0.0.262 to 0.0.265
2023-05-10 13:45:33 +02:00
dependabot[bot]
b7b451dace build(deps-dev): bump ruff from 0.0.262 to 0.0.265
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.262 to 0.0.265.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.262...v0.0.265)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 14:58:18 +00:00
Aayush Goel
d91070c116 Update detect_duplicate_features.py 2023-05-08 20:17:29 +05:30
Aayush Goel
39d2a70679 Update detect_duplicate_features.py
Using get_rules menthod to get set of all existing rules.
2023-05-08 17:29:01 +05:30
Aayush Goel
ec6b6a2266 Update detect_duplicate_features.py 2023-05-08 14:58:30 +05:30
Aayush Goel
9eacf72366 Update detect_duplicate_features.py
loading yaml file using capa.rule.Rule.from_yaml.
Returning any exception/errors occuring while checking the files.
2023-05-06 17:36:13 +05:30
Aayush Goel
30516c33b7 Update detect_duplicate_features.py
Improved parse routine based on suggestions.

Co-Authored-By: Moritz <mr-tz@users.noreply.github.com>
2023-05-05 15:17:43 +05:30
Aayush Goel
615628805c Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1451 2023-05-04 20:04:28 +05:30
Moritz
8bac455bc9 Merge pull request #1472 from Aayush-Goel-04/Aayush-Goel-04/update_CHANGELOG.md
Update CHANGELOG.md
2023-05-04 16:26:55 +02:00
Aayush Goel
0945d9aea2 Update CHANGELOG.md 2023-05-04 19:55:17 +05:30
Aayush Goel
45c6e74945 Update CHANGELOG.md 2023-05-04 19:32:20 +05:30
Aayush Goel
b32ab87bb7 Merge branch 'mandiant:master' into Aayush-Goel-04/Issue#1451 2023-05-04 19:20:13 +05:30
Willi Ballenthin
8d2a186b1a Merge pull request #1471 from Aayush-Goel-04/Aayush-Goel-04/Issue#1458
Added try/except blocks to detect_elf_os in elf.py for improved ELF parsing and OS detection
2023-05-04 15:19:06 +02:00
Aayush Goel
a62996420f Update elf.py
corrected pre-formatted strings
2023-05-04 18:29:15 +05:30
Aayush Goel
7dc4c44393 Update elf.py
Added more try/excepts around the parsing code in detect_elf_os
2023-05-04 17:13:07 +05:30
Moritz
6ffcbfef3d Merge pull request #1469 from mr-tz/mr-tz-patch-1
Don't test BN - attempt 3
2023-05-04 13:33:36 +02:00
Aayush Goel
1c558a203d Update detect_duplicate_features.py
Added a main routine and using argparse to retrieve these from the command line
2023-05-03 22:32:22 +05:30
Moritz
ed5dabe432 Update tests.yml 2023-05-03 18:16:23 +02:00
Capa Bot
ce28d60edf Sync capa rules submodule 2023-05-02 10:28:10 +00:00
Capa Bot
afa9410209 Sync capa rules submodule 2023-05-02 09:43:49 +00:00
Aayush Goel
09865ccd9b Fixes Linting Issues
Update detect_duplicate_features.py
2023-04-27 06:46:02 +05:30
Aayush Goel
256611bef5 Create detect_duplicate_features.py
Fixes #1451
Python script to detect feature overlap between new and existing CAPA rules. Checks if the a feature in new rules exists in an existing rule
2023-04-27 06:00:38 +05:30
Capa Bot
7b0fac27dc Sync capa rules submodule 2023-04-25 19:19:19 +00:00
Yacine Elhamer
c7b65cfe8a Shdr constructor: Use direct member access to get vstruct's section header information
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-04-25 17:23:32 +01:00
Moritz
f811b6b803 Merge pull request #1449 from mandiant/dependabot/pip/pyinstaller-5.10.1
build(deps-dev): bump pyinstaller from 5.9.0 to 5.10.1
2023-04-25 14:08:07 +02:00
Moritz
ba43513172 Merge pull request #1435 from Vector35/fix_bn_path_detection
Fix BN installation path detection does not work with Python 3.11
2023-04-25 11:37:34 +02:00
dependabot[bot]
f3bb2169c0 build(deps-dev): bump pyinstaller from 5.9.0 to 5.10.1
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 5.9.0 to 5.10.1.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v5.9.0...v5.10.1)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-25 09:36:26 +00:00
dependabot[bot]
68b58f979b build(deps): bump termcolor from 2.2.0 to 2.3.0 (#1459)
* build(deps): bump termcolor from 2.2.0 to 2.3.0

Bumps [termcolor](https://github.com/termcolor/termcolor) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/termcolor/termcolor/releases)
- [Changelog](https://github.com/termcolor/termcolor/blob/main/CHANGES.md)
- [Commits](https://github.com/termcolor/termcolor/compare/2.2.0...2.3.0)

---
updated-dependencies:
- dependency-name: termcolor
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-25 11:35:34 +02:00
Moritz
8e80bc844d Test BN 2 (#1462)
* Update .github/workflows/tests.yml
2023-04-25 11:35:07 +02:00
Willi Ballenthin
a45cab06d3 Merge pull request #1461 from mandiant/dependabot/pip/ruff-0.0.262
build(deps-dev): bump ruff from 0.0.260 to 0.0.262
2023-04-25 10:28:18 +02:00
Yacine Elhamer
695508aa4c insn.py: Update extract_insn_api_features() to optimize by means of viv rather than function attributes 2023-04-25 08:42:53 +01:00
Moritz
957083d805 fix ELF parse error (#1454)
* fix ELF parse error

* add ELF header parsing test
2023-04-25 08:46:56 +02:00
dependabot[bot]
2aac99b037 build(deps): bump protobuf from 4.22.1 to 4.22.3 (#1448)
Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 4.22.1 to 4.22.3.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/generate_changelog.py)
- [Commits](https://github.com/protocolbuffers/protobuf/compare/v4.22.1...v4.22.3)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-25 06:36:06 +02:00
Moritz
2401dc785c update viv dependencies and fix (#1342)
* update dependencies and fix

* pyinstaller: add hook for new viv pas

* pyinstaller: hooks: remove duplicate entries and old analysis pass

* Update setup.py

* update hidden imports

---------

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-04-25 06:34:40 +02:00
Moritz
f902add0ce Merge pull request #1457 from yelhamer/bugfix-symtab
SymTab _parse(): Bugfixes for the struct unpacking and for handling symtabs with a null entry size
2023-04-24 19:35:23 +02:00
Yacine Elhamer
2faae5d022 SymTab: Update unpacking format
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-04-24 17:57:06 +01:00
dependabot[bot]
2a2878bba0 build(deps-dev): bump ruff from 0.0.260 to 0.0.262
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.260 to 0.0.262.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.260...v0.0.262)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 14:58:25 +00:00
Moritz
2bb6f924cd Merge pull request #1447 from mandiant/dependabot/pip/pytest-7.3.1
build(deps-dev): bump pytest from 7.3.0 to 7.3.1
2023-04-24 12:37:38 +02:00
Yacine Elhamer
ee881ab82f code style: Fix the format of the committed code 2023-04-23 02:31:11 +01:00
Yacine Elhamer
b32a8ca510 insn.py: Get the symtab api extractor to yield FunctionName features as well 2023-04-23 01:20:25 +01:00
Yacine Elhamer
b766d957b0 insn.py: rewire symbol parsing to use SymTab instead of vivisect 2023-04-22 01:36:57 +01:00
Yacine Elhamer
e7ccea44e7 Shdr: add a constructor for vivisect's shdr representation 2023-04-22 01:33:00 +01:00
Yacine Elhamer
861e96d33e update CHANGELOG.md 2023-04-22 01:16:42 +01:00
Yacine Elhamer
07e6407115 _parse(): safeguard against zero entry size 2023-04-22 01:10:26 +01:00
Yacine Elhamer
69d44cdc16 _parse(): fix section header unpacking field size 2023-04-22 01:09:04 +01:00
Yacine Elhamer
97c8fd0525 Update CHANGELOG.md
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-04-21 19:36:20 +01:00
Moritz
259dfaed11 Update tests.yml 2023-04-21 17:24:06 +02:00
dependabot[bot]
bf02b2ecb4 build(deps-dev): bump pytest from 7.3.0 to 7.3.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.3.0 to 7.3.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.3.0...7.3.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-21 14:18:11 +00:00
Moritz
88c78bb411 only test binaryninja on non-forks 2023-04-21 16:15:27 +02:00
Capa Bot
2c73f08364 Sync capa-testfiles submodule 2023-04-21 14:06:49 +00:00
Capa Bot
467c19be97 Sync capa rules submodule 2023-04-19 17:01:01 +00:00
Capa Bot
96d7f20980 Sync capa rules submodule 2023-04-19 15:56:44 +00:00
Capa Bot
8965fc8a79 Sync capa rules submodule 2023-04-17 16:11:59 +00:00
Capa Bot
f4968bc1f1 Sync capa rules submodule 2023-04-17 15:59:53 +00:00
Capa Bot
fe0702a06b Sync capa-testfiles submodule 2023-04-17 15:58:44 +00:00
Yacine Elhamer
44254bfffe Update CHANGELOG.md
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-04-17 09:51:39 +01:00
Willi Ballenthin
c85050ac1a Merge pull request #1405 from ooprathamm/ruff
Linting with ruff
2023-04-17 10:46:24 +02:00
Yacine Elhamer
21f2cb6e6f Update CHANGELOG.md 2023-04-14 04:25:24 +01:00
Yacine Elhamer
c71cb55051 insn extractor: Add static api extraction using .symtab 2023-04-14 04:07:05 +01:00
Willi Ballenthin
6ba5b2b72b Merge pull request #1442 from Vector35/fix_bn_error
Check if caller.llil is None before accessing its properties
2023-04-12 14:20:51 +02:00
Xusheng
dd207fb238 Check if caller.llil is None before accessing its properties 2023-04-12 15:13:40 +08:00
Willi Ballenthin
e9e06bb571 Merge pull request #1439 from mandiant/dependabot/pip/mypy-1.2.0
build(deps-dev): bump mypy from 1.1.1 to 1.2.0
2023-04-10 20:48:47 +02:00
Willi Ballenthin
ae0e0a03a3 Merge pull request #1437 from mandiant/dependabot/pip/types-protobuf-4.22.0.2
build(deps-dev): bump types-protobuf from 4.22.0.1 to 4.22.0.2
2023-04-10 20:47:39 +02:00
Willi Ballenthin
526fc15082 Merge pull request #1436 from mandiant/dependabot/pip/pytest-7.3.0
build(deps-dev): bump pytest from 7.1.3 to 7.3.0
2023-04-10 20:46:53 +02:00
dependabot[bot]
271107436b build(deps-dev): bump mypy from 1.1.1 to 1.2.0
Bumps [mypy](https://github.com/python/mypy) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v1.1.1...v1.2.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 14:58:07 +00:00
dependabot[bot]
eaa4e15439 build(deps-dev): bump types-protobuf from 4.22.0.1 to 4.22.0.2
Bumps [types-protobuf](https://github.com/python/typeshed) from 4.22.0.1 to 4.22.0.2.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-protobuf
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 14:57:58 +00:00
dependabot[bot]
7cfeebfff7 build(deps-dev): bump pytest from 7.1.3 to 7.3.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.3 to 7.3.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.1.3...7.3.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 14:57:56 +00:00
Xusheng
6f3bffe689 Fix BN installation path detection does not work with Python 3.11 2023-04-10 11:45:05 +08:00
Moritz
7c4a46b7b4 update to v5.1.0 (#1429)
* update to v5.1.0

---------

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-04-06 12:55:25 +02:00
Pratham Chauhan
efb07fafb3 fix 2023-04-05 22:16:00 +05:30
Pratham Chauhan
eedd885683 fix black 2023-04-05 17:44:57 +05:30
Pratham Chauhan
e6248cd9ed solve failing binja 2023-04-05 17:43:11 +05:30
Pratham Chauhan
3d1ef51863 revert 2023-04-05 17:33:05 +05:30
Pratham Chauhan
068ac0ca2c fix black 2023-04-05 16:29:53 +05:30
naikordian
8fe88f601f fix: Warning user to install signatures (#1420)
* fix: Warning user to install signatures

---------

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-04-05 12:59:41 +02:00
Pratham Chauhan
eef1548baa fix capy2yara.py 2023-04-05 16:28:00 +05:30
Pratham Chauhan
6eaa46ea9a revert bninja change 2023-04-05 13:32:15 +05:30
ooprathamm
6641c8c9c9 fixing error issue
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-04-04 23:07:04 +05:30
Pratham Chauhan
a40126aeff reformatting with black 2023-04-04 19:10:40 +05:30
Pratham Chauhan
ccc51dab35 resolve merge conflict 2023-04-04 18:56:26 +05:30
Pratham Chauhan
89c6c235f7 resolve conflict 2023-04-04 18:46:31 +05:30
Pratham Chauhan
a260b35c9d --fix 2023-04-04 18:28:43 +05:30
Pratham Chauhan
c04774b4b1 solving unresolvable issues using --fix and ignoring some issues 2023-04-04 18:27:30 +05:30
Willi Ballenthin
d46cf5b519 Merge pull request #1427 from mandiant/dependabot/pip/types-protobuf-4.22.0.1
build(deps-dev): bump types-protobuf from 4.22.0.0 to 4.22.0.1
2023-04-04 11:21:49 +02:00
Willi Ballenthin
29682cf767 Merge pull request #1425 from mandiant/dependabot/pip/black-23.3.0
build(deps-dev): bump black from 23.1.0 to 23.3.0
2023-04-04 11:21:23 +02:00
Willi Ballenthin
42df936336 Merge pull request #1428 from mandiant/dependabot/pip/pytest-instafail-0.5.0
build(deps-dev): bump pytest-instafail from 0.4.2 to 0.5.0
2023-04-04 11:20:52 +02:00
dependabot[bot]
fe6117e87a build(deps-dev): bump pytest-instafail from 0.4.2 to 0.5.0
Bumps [pytest-instafail](https://github.com/pytest-dev/pytest-instafail) from 0.4.2 to 0.5.0.
- [Release notes](https://github.com/pytest-dev/pytest-instafail/releases)
- [Changelog](https://github.com/pytest-dev/pytest-instafail/blob/master/CHANGES.rst)
- [Commits](https://github.com/pytest-dev/pytest-instafail/compare/v0.4.2...v0.5.0)

---
updated-dependencies:
- dependency-name: pytest-instafail
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-04 07:40:27 +00:00
dependabot[bot]
04ca770545 build(deps-dev): bump black from 23.1.0 to 23.3.0
Bumps [black](https://github.com/psf/black) from 23.1.0 to 23.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.1.0...23.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-04 07:40:03 +00:00
dependabot[bot]
43f3f31d69 build(deps-dev): bump types-protobuf from 4.22.0.0 to 4.22.0.1
Bumps [types-protobuf](https://github.com/python/typeshed) from 4.22.0.0 to 4.22.0.1.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-protobuf
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-04 07:39:46 +00:00
Willi Ballenthin
acd0020413 Merge pull request #1423 from mandiant/mypy-111
more mypy v1.1.1 fixes
2023-04-03 21:48:51 +02:00
Capa Bot
0002b05418 Sync capa rules submodule 2023-04-03 17:08:37 +00:00
Willi Ballenthin
545e198257 ci: bump more ubuntu images 2023-04-03 17:54:41 +02:00
Willi Ballenthin
d4b83e3f8a ci: pyinstaller: update to use ubuntu 20.04 for building linux
executables
2023-04-03 17:39:43 +02:00
Willi Ballenthin
efcc2e0dd4 elf: remove old print statement 2023-04-03 16:13:28 +02:00
Willi Ballenthin
5e0d6176a1 elf: parse associated strtab for symtab 2023-04-03 16:09:14 +02:00
Willi Ballenthin
e240372a90 result document: document subscope/match handling 2023-04-03 15:37:46 +02:00
Willi Ballenthin
a64a88981f tests: add another test demonstrating rd format output 2023-04-03 15:35:20 +02:00
Willi Ballenthin
bc8df09be5 result document: more deserialization 2023-04-03 15:27:48 +02:00
Willi Ballenthin
b09e3e69f2 wip: result document: deserialize into capa object instances 2023-04-03 15:04:15 +02:00
Willi Ballenthin
43128404be elf: remove old debugging code 2023-04-03 15:04:00 +02:00
Willi Ballenthin
28e85aa548 main: mypy 2023-04-03 13:48:30 +02:00
Willi Ballenthin
30c14210ed main: better separate logic for deserializing result/freeze/other 2023-04-03 13:44:19 +02:00
Willi Ballenthin
d2fc740278 result document: mypy 2023-04-03 13:44:09 +02:00
Capa Bot
cbe30199ff Sync capa-testfiles submodule 2023-04-03 11:31:24 +00:00
Willi Ballenthin
3f5d9c79f9 elf: add type hints and Symbol dataclass 2023-04-03 13:30:02 +02:00
Willi Ballenthin
59332c2e94 tests: fixtures: add paths for new ELF test file 2023-04-03 13:16:03 +02:00
Willi Ballenthin
d230780443 pep8 2023-04-03 13:00:02 +02:00
Willi Ballenthin
7387c073fb Merge pull request #1412 from manasghandat/fix-shadowed-variable
Fix shadowed variable
2023-04-03 12:58:15 +02:00
Willi Ballenthin
535ba622ae Merge pull request #1422 from yelhamer/feature-symtab-os-guess
ELF OS detection: add support for guessing that's based on .symtab entries
2023-04-03 08:41:47 +02:00
Capa Bot
c6b634f3ae Sync capa-testfiles submodule 2023-04-03 06:41:30 +00:00
Willi Ballenthin
386baec3c5 elf: hints and formatting 2023-04-03 08:40:41 +02:00
Yacine Elhamer
b2ead45ad4 tests: Add test for sample 2bf18d 2023-04-02 21:57:22 +01:00
Yacine Elhamer
74284e9dad bugfix: potential reference to uninitialized variables 2023-04-02 21:56:28 +01:00
Yacine Elhamer
270077bc73 SymTab class: update get_symbols() type and add return-value comment 2023-04-02 20:59:09 +01:00
Yacine Elhamer
367a0c483c rename the SYMTAB class to SymTab 2023-04-02 20:49:58 +01:00
Yacine Elhamer
8a272e92c7 format: removed tabs
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-04-02 20:38:44 +01:00
Yacine Elhamer
2d1105dba9 format: update elf.py to use isort and black format
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-04-02 20:36:34 +01:00
Yacine Elhamer
c798996f6e detect_elf_os(): Integrate symbol-based guessing ability 2023-04-02 18:11:11 +01:00
Yacine Elhamer
ef0e4bd4fd os-guessing: Add symtab-guessing capability 2023-04-02 18:07:46 +01:00
Yacine Elhamer
bfaee2c402 Add a class (SYMTAB) for the symbol table 2023-04-02 18:07:46 +01:00
Yacine Elhamer
1f6cd807a4 Shdr dataclass: add sh_entsize member 2023-04-02 18:07:22 +01:00
Willi Ballenthin
6f416dfefb Merge pull request #1418 from stevemk14ebr/master
Remove dynsym library name for ELF imports
2023-04-01 13:54:07 +02:00
Capa Bot
06c71a7f2b Sync capa rules submodule 2023-03-31 17:40:58 +00:00
Stephen Eckels
270350f8d1 Update CHANGELOG.md
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-03-31 13:26:41 -04:00
Stephen Eckels
c603b92bc5 Merge branch 'master' of https://github.com/stevemk14ebr/capa 2023-03-31 13:25:45 -04:00
Stephen Eckels
59be399dac Revert line removal 2023-03-31 13:25:37 -04:00
Capa Bot
7f39cb1bc3 Sync capa rules submodule 2023-03-31 14:03:51 +00:00
manasghandat
d09e1c8ee2 fix linting error 2023-03-31 12:29:26 +05:30
manasghandat
c1735b6033 Merge branch 'mandiant:master' into fix-shadowed-variable 2023-03-31 12:27:43 +05:30
Stephen Eckels
1921961cff Update todo comment to link issue
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-03-30 13:23:29 -04:00
Stephen Eckels
3cd766630f Update changelog 2023-03-30 13:21:37 -04:00
manasghandat
fac548a76e Update capa/render/proto/__init__.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-03-30 22:51:17 +05:30
manasghandat
24f4ebef23 Update capa/render/proto/__init__.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-03-30 22:51:07 +05:30
Willi Ballenthin
99ee317fd0 Merge pull request #1396 from ooprathamm/read-render
Towards improving read and rendering of results
2023-03-30 13:03:27 +02:00
Pratham Chauhan
456f6e0003 fix broken arch logic 2023-03-30 16:18:52 +05:30
Willi Ballenthin
1ccd2c4d0f tests: fix proto tests on windows (#1417)
closes  #1416
2023-03-30 11:45:03 +02:00
Willi Ballenthin
f42b5b1088 Merge pull request #1409 from mandiant/dependabot/pip/protobuf-4.22.1
build(deps): bump protobuf from 4.21.12 to 4.22.1
2023-03-30 11:17:14 +02:00
Pratham Chauhan
ed64986af8 adds a ruff.toml file for config 2023-03-30 14:22:11 +05:30
Pratham Chauhan
1b90a28acd resolved merge conflicts 2023-03-30 11:05:32 +05:30
Pratham Chauhan
cd0e0ce4d1 remove unused import 2023-03-30 10:52:05 +05:30
Pratham Chauhan
7cb4ea9273 Fix lint issues 2023-03-30 10:35:31 +05:30
Stephen Eckels
66e374a343 Update changelog 2023-03-29 16:01:31 -04:00
Stephen Eckels
5e8262d3c0 Remove dynsym from elf entirely 2023-03-29 15:58:16 -04:00
Willi Ballenthin
6bb14d0874 Merge pull request #1415 from mandiant/f-strings
use f-strings as appropriate
2023-03-29 20:47:12 +02:00
Pratham Chauhan
c3fdab8ec5 Add new test test_rdoc_to_capa 2023-03-29 22:57:11 +05:30
Pratham Chauhan
237554d84a Fix broken logic for FORMAT_FREEZE 2023-03-29 22:32:12 +05:30
Pratham Chauhan
6ed7aca5be remove rule param 2023-03-29 19:50:07 +05:30
Pratham Chauhan
a13ce094b3 use rd/test json 2023-03-29 19:41:14 +05:30
Pratham Chauhan
6806b8f5a7 use pydantic.parse_file 2023-03-29 19:02:45 +05:30
manasghandat
e3d9386239 Merge branch 'mandiant:master' into fix-shadowed-variable 2023-03-29 18:31:28 +05:30
dependabot[bot]
fbdf92367e build(deps): bump protobuf from 4.21.12 to 4.22.1
Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 4.21.12 to 4.22.1.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/generate_changelog.py)
- [Commits](https://github.com/protocolbuffers/protobuf/commits/v4.22.1)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-29 12:52:59 +00:00
Willi Ballenthin
2ec96d7f13 Merge pull request #1408 from mandiant/dependabot/pip/pydantic-1.10.7
build(deps): bump pydantic from 1.10.6 to 1.10.7
2023-03-29 14:52:45 +02:00
Willi Ballenthin
1c457d3428 Merge pull request #1407 from mandiant/dependabot/pip/types-protobuf-4.22.0.0
build(deps-dev): bump types-protobuf from 4.21.0.5 to 4.22.0.0
2023-03-29 14:52:14 +02:00
Pratham Chauhan
fe1193f374 removes unused imports 2023-03-29 16:12:17 +05:30
Pratham Chauhan
abbf3db2ac Revert "remove unused imports"
This reverts commit 9e12c563bc.
2023-03-29 16:11:21 +05:30
Pratham Chauhan
5a1009520d Revert "Revert "introducing match strings constant for formats""
This reverts commit b49fb7fcf9.
2023-03-29 16:10:44 +05:30
Pratham Chauhan
b49fb7fcf9 Revert "introducing match strings constant for formats"
This reverts commit 530e28cbc3.
2023-03-29 16:06:20 +05:30
Pratham Chauhan
9e12c563bc remove unused imports 2023-03-29 16:02:17 +05:30
Pratham Chauhan
530e28cbc3 introducing match strings constant for formats 2023-03-29 16:00:02 +05:30
Pratham Chauhan
637dd6bf0a Added a unit test 2023-03-29 15:51:25 +05:30
Pratham Chauhan
fdc9530352 seperating loading json and to_capa logic 2023-03-29 08:34:06 +05:30
manasghandat
4990f7a2c8 Fix requested changes 2023-03-28 22:11:37 +05:30
Capa Bot
b5f274bf56 Sync capa rules submodule 2023-03-28 14:07:51 +00:00
Willi Ballenthin
ac2d01a60a use f-strings as appropriate
closes #600
2023-03-28 11:43:49 +02:00
Willi Ballenthin
95bdaf072b Merge pull request #1399 from ggold7046/patch-15
Update utils.py
2023-03-28 09:47:11 +02:00
Capa Bot
af1500825a Sync capa rules submodule 2023-03-28 07:20:10 +00:00
AG
cd2ef15a8a Update CHANGELOG.md
Update changelog to reflect changes introduced in pull request #1399
2023-03-28 01:11:23 +05:30
Pratham Chauhan
02359e5e84 fix 2023-03-27 22:22:25 +05:30
dependabot[bot]
d873cc0257 build(deps): bump pydantic from 1.10.6 to 1.10.7
Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.10.6 to 1.10.7.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/v1.10.7/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v1.10.6...v1.10.7)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 14:09:09 +00:00
dependabot[bot]
ea2acea668 build(deps-dev): bump types-protobuf from 4.21.0.5 to 4.22.0.0
Bumps [types-protobuf](https://github.com/python/typeshed) from 4.21.0.5 to 4.22.0.0.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-protobuf
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 14:08:45 +00:00
Pratham Chauhan
84052c3ac5 init 2023-03-27 19:21:55 +05:30
Willi Ballenthin
4a40732cad Merge pull request #1406 from mandiant/williballenthin-patch-1
ci: tests: run binja after code style/linter
2023-03-27 13:17:47 +02:00
Willi Ballenthin
cd9f32ced5 Merge pull request #1398 from mandiant/fix-shadowed-variable
main: fix variable shadowing module os
2023-03-27 13:17:32 +02:00
Willi Ballenthin
2bedc6b181 ci: tests: run binja after code style/linter 2023-03-27 11:47:53 +02:00
Pratham Chauhan
e26deb472e Update CHANGELOG.md 2023-03-26 22:54:12 +05:30
Pratham Chauhan
78d0111a6c Final changes 2023-03-26 22:09:04 +05:30
Capa Bot
d61c85c171 Sync capa rules submodule 2023-03-26 09:29:01 +00:00
Pratham Chauhan
03f0034d33 working meta parsing 2023-03-25 14:47:59 +05:30
manasghandat
3f2e698684 fix mypy issue 2023-03-24 22:20:37 +05:30
manasghandat
259aa53de4 Merge branch 'fix-shadowed-variable' of https://github.com/mandiant/capa into fix-shadowed-variable 2023-03-24 21:11:39 +05:30
manasghandat
7915fb3fb6 Merge branch 'master' of https://github.com/mandiant/capa 2023-03-24 21:06:41 +05:30
AG
fbb348bc82 Update utils.py
Changed the colour/highlight to "cyan" instead of "blue" for easy noticing.
2023-03-24 20:50:45 +05:30
Willi Ballenthin
a8552e6b96 Merge pull request #1316 from mandiant/wb-proto
protobuf support
2023-03-24 11:51:56 +01:00
Willi Ballenthin
4be3fe1628 Merge branch 'master' into wb-proto 2023-03-24 11:51:45 +01:00
Willi Ballenthin
a087045322 Merge pull request #1387 from manasghandat/main
Fix mypy update 1.1.1 by dependabot
2023-03-24 11:51:01 +01:00
Pratham Chauhan
248229a383 Functioning parse_raw 2023-03-24 10:29:37 +05:30
Pratham Chauhan
0ff22d319f fix 2023-03-24 01:22:29 +05:30
manasghandat
a1dfcc73dd fix basicblockfeature 2023-03-23 21:20:06 +05:30
Willi Ballenthin
3e98115dc2 main: fix variable shadowing module os 2023-03-23 16:11:21 +01:00
Willi Ballenthin
ddc52fa21c Merge branch 'master' of personal.github.com:mandiant/capa 2023-03-23 16:04:54 +01:00
xusheng
986e2e6057 Merge pull request #1 from mandiant/binja-ci 2023-03-24 18:39:12 +08:00
Capa Bot
793057c202 Sync capa-testfiles submodule 2023-03-24 09:30:40 +00:00
Capa Bot
3bf9cacaec Sync capa rules submodule 2023-03-24 08:55:50 +00:00
Capa Bot
bed4593d04 Sync capa-testfiles submodule 2023-03-23 18:29:19 +00:00
Willi Ballenthin
e8082173ad tests: add test demonstrating to/from proto scripts 2023-03-23 15:42:43 +01:00
Willi Ballenthin
b1f4035530 Merge branch 'wb-proto' of personal.github.com:mandiant/capa into wb-proto 2023-03-23 15:30:10 +01:00
Willi Ballenthin
0d4a92a351 gitignore 2023-03-23 15:27:32 +01:00
Willi Ballenthin
89803e7523 ci: add binary ninja installation and test invocation 2023-03-23 14:17:26 +01:00
Willi Ballenthin
613ce92cfd tests: remove old debugging statements 2023-03-23 14:14:04 +01:00
Willi Ballenthin
8bde277be2 ci: binja: update installer to use root 2023-03-23 14:11:48 +01:00
Willi Ballenthin
3be7bbbf88 ci: binja: log more 2023-03-23 14:06:36 +01:00
Willi Ballenthin
d8aa276f25 tests: debug binja api 2023-03-23 14:04:14 +01:00
Willi Ballenthin
dcddef09dc ci: binja: inject secrets 2023-03-23 14:00:28 +01:00
Willi Ballenthin
ad442aaae3 ci: binja: fix curl output 2023-03-23 13:58:04 +01:00
Willi Ballenthin
21ecc7618a ci: binja: fix curl 2023-03-23 13:56:08 +01:00
Willi Ballenthin
8f8a0b118f ci: add test workflow for binja testing 2023-03-23 13:52:58 +01:00
Pratham Chauhan
0358b46fcd add FORMAT_RESULT 2023-03-23 18:07:03 +05:30
Willi Ballenthin
1a29077b45 tests: binja: don't crash on bad license - log instead 2023-03-23 12:38:52 +01:00
Willi Ballenthin
c249b841e8 tests: binja: ensure the license is valid 2023-03-23 12:37:06 +01:00
Willi Ballenthin
7d12942cf7 Merge branch 'binja_backend' of github.com:Vector35/capa into Vector35-binja_backend 2023-03-23 11:31:25 +01:00
Willi Ballenthin
c52b0a22e0 tests: simplify loading of result document from file 2023-03-23 11:04:53 +01:00
Willi Ballenthin
840145f947 Update CHANGELOG.md 2023-03-23 11:02:58 +01:00
Willi Ballenthin
10d6e55d62 proto: remove main entrypoint 2023-03-23 10:58:51 +01:00
Willi Ballenthin
80112bac64 add scripts showing conversion to/from protobuf format 2023-03-23 10:58:22 +01:00
Willi Ballenthin
49ff9d5a7c pep8 2023-03-23 10:58:13 +01:00
Willi Ballenthin
1044709803 tests: proto: test byte representation, not messages 2023-03-23 10:57:35 +01:00
Willi Ballenthin
252f5cebb7 proto: remove old code 2023-03-23 10:35:41 +01:00
Willi Ballenthin
e8ddee4782 Merge branch 'master' of personal.github.com:mandiant/capa into wb-proto 2023-03-23 10:35:30 +01:00
Willi Ballenthin
8daa1c032c Merge pull request #1350 from captainGeech42/issues/1348
feature: support for OS override
2023-03-23 10:32:39 +01:00
Willi Ballenthin
beccf28d09 Merge branch 'rd-hardening' into wb-proto 2023-03-23 10:31:29 +01:00
Willi Ballenthin
5ac3414490 Merge pull request #1395 from HongThatCong/master
Update __init__.py
2023-03-23 10:31:14 +01:00
Willi Ballenthin
5d49f5a1d2 Merge branch 'master' of personal.github.com:mandiant/capa into wb-proto 2023-03-23 10:30:07 +01:00
Capa Bot
41bf5f0926 Sync capa-testfiles submodule 2023-03-23 09:29:26 +00:00
Capa Bot
4c5a16a1db Sync capa rules submodule 2023-03-23 07:49:17 +00:00
Capa Bot
85fb9aa99f Sync capa rules submodule 2023-03-23 07:48:11 +00:00
Capa Bot
57d34087dd Sync capa-testfiles submodule 2023-03-22 19:50:38 +00:00
Capa Bot
2d65b4b2a1 Sync capa rules submodule 2023-03-22 19:43:40 +00:00
Willi Ballenthin
d068faa35e tests: remove old comment 2023-03-22 13:24:42 +01:00
Willi Ballenthin
1c33cd4470 pep8 2023-03-22 13:12:22 +01:00
Willi Ballenthin
21e410cc77 proto: implement deserialization from protobuf format 2023-03-22 13:08:10 +01:00
Willi Ballenthin
68ebd87127 tests: proto: fix property name 2023-03-22 11:22:12 +01:00
Willi Ballenthin
62069e9e59 tests: proto: fix module references 2023-03-22 11:21:59 +01:00
Willi Ballenthin
14a2088606 proto: move impl to top level module 2023-03-22 11:16:37 +01:00
Willi Ballenthin
114c3854e7 tests: add round trip tests for proto 2023-03-22 11:15:50 +01:00
Willi Ballenthin
26ca593fad proto: sketch from pb2 routines 2023-03-22 11:15:34 +01:00
Willi Ballenthin
ec785f9d6d proto: don't use name property due to top level python decorator name 2023-03-22 11:03:18 +01:00
Willi Ballenthin
f54ef35a7a mypy 2023-03-22 10:58:24 +01:00
Willi Ballenthin
e0b57fc74e insn: fix type annotation for operand index 2023-03-22 10:57:17 +01:00
Willi Ballenthin
4754a84a8a pep8 2023-03-22 10:52:40 +01:00
Willi Ballenthin
02fdf41969 tests: add tests demonstrating result document round tripping 2023-03-22 10:47:45 +01:00
Willi Ballenthin
92e75ee89b insn: document ranges of numbers and offsets 2023-03-22 10:09:57 +01:00
Willi Ballenthin
7c2b6a3161 proto: update generate pb2 2023-03-22 10:00:51 +01:00
Willi Ballenthin
26a8647444 proto: revert address field name change 2023-03-22 10:00:12 +01:00
Willi Ballenthin
cae7c4d0a7 proto: update doc and field numbers 2023-03-22 09:58:03 +01:00
Willi Ballenthin
27a5e17a3e proto: rename address value field 2023-03-22 09:52:01 +01:00
Willi Ballenthin
a9ba133506 bulk-process: fix some variable references 2023-03-22 09:48:20 +01:00
Willi Ballenthin
eb20724d78 Merge branch 'master' into wb-proto 2023-03-22 09:46:03 +01:00
Willi Ballenthin
1b9e486c49 Merge pull request #1351 from mandiant/wb-mr-proto
WIP: proto translation
2023-03-22 09:44:59 +01:00
Willi Ballenthin
7ef167fcd0 Update scripts/bulk-process.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-03-22 09:44:00 +01:00
Hồng Thất Công
9db106e3f0 Update __init__.py
Update IDA plugin
2023-03-22 11:58:46 +07:00
manasghandat
b4052e5a64 Add appropriate comments 2023-03-22 07:49:20 +05:30
manasghandat
9a77f18ced Add appropriate comments 2023-03-22 07:45:59 +05:30
Capa Bot
03996f2b82 Sync capa rules submodule 2023-03-21 21:04:25 +00:00
Willi Ballenthin
53ca96fcee result document: make all classes frozen and forbid extra attributes 2023-03-21 17:37:27 +01:00
Willi Ballenthin
c1ca4ab703 isort 2023-03-21 17:22:43 +01:00
Willi Ballenthin
43bcf401b2 bulk-process: reference error 2023-03-21 16:57:16 +01:00
Willi Ballenthin
f1c495dc0a *: use FORMAT_AUTO instead of string literal 2023-03-21 16:54:48 +01:00
Willi Ballenthin
98eb28704c main: don't embed format/os overrides in metadata 2023-03-21 16:47:11 +01:00
Willi Ballenthin
1f3582c9c3 mypy 2023-03-21 16:45:24 +01:00
Willi Ballenthin
62f7bddd4d Merge pull request #1389 from ggold7046/patch-16
Update view.py
2023-03-21 16:31:05 +01:00
AG
b097569607 Update view.py
Updated with f string for better readability.
2023-03-21 19:53:10 +05:30
manasghandat
da6f72c20a fix mypy fails 2023-03-21 19:10:11 +05:30
manasghandat
00e94d976a fix linting issue 2023-03-21 18:51:51 +05:30
manasghandat
d1d6db877d Merge branch 'mandiant:master' into main 2023-03-21 18:47:16 +05:30
manasghandat
da3e3c6bb4 fix mypy fails 2023-03-21 18:46:22 +05:30
Willi Ballenthin
e57be09823 Merge branch 'issues/1348' of github.com:captainGeech42/capa into issues/1348 2023-03-21 14:04:46 +01:00
Willi Ballenthin
7598a97888 Merge branch 'master' of personal.github.com:mandiant/capa into pr-1350 2023-03-21 14:02:02 +01:00
Willi Ballenthin
ebaf51ce56 Merge branch 'master' into issues/1348 2023-03-21 13:54:52 +01:00
Willi Ballenthin
0cf8b154a4 pep8 2023-03-21 13:53:59 +01:00
Willi Ballenthin
b420d6bbb2 Merge pull request #1386 from mandiant/dependabot/pip/pyinstaller-5.9.0
build(deps-dev): bump pyinstaller from 5.8.0 to 5.9.0
2023-03-21 13:04:57 +01:00
mr-tz
6086cc5e18 update number/offset understanding 2023-03-20 18:11:24 +01:00
mr-tz
c3ed12d8d4 add helper function 2023-03-20 17:46:36 +01:00
mr-tz
2d98c9e3c4 address mypy warnings 2023-03-20 17:45:55 +01:00
mr-tz
0933040d0b remove protobuf from rd scheme generation test 2023-03-20 17:45:23 +01:00
mr-tz
12046e698e don't change child data 2023-03-20 17:43:21 +01:00
mr-tz
73ac83bd06 reformat changelog 2023-03-20 16:58:06 +01:00
mr-tz
631685472d add assert_never 2023-03-20 16:55:42 +01:00
mr-tz
32bcf999b8 remove proto from pydantic generation code 2023-03-20 16:53:44 +01:00
dependabot[bot]
008f6d1839 build(deps-dev): bump pyinstaller from 5.8.0 to 5.9.0
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 5.8.0 to 5.9.0.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v5.8.0...v5.9.0)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-20 14:58:43 +00:00
dependabot[bot]
1746a640cc build(deps): bump pydantic from 1.10.5 to 1.10.6 (#1380)
Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.10.5 to 1.10.6.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/v1.10.6/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v1.10.5...v1.10.6)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-17 14:12:20 +01:00
Capa Bot
d5937e4af5 Sync capa rules submodule 2023-03-16 17:41:19 +00:00
manasghandat
1336796c0c code style : update remaining files (#1353)
* code style: update string formatting using fstrings

---------

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-03-16 11:16:18 +01:00
manasghandat
2efcfcf239 fix merge conflicts 2023-03-15 07:19:41 +05:30
manasghandat
8f2ffe8526 fix code style 2023-03-15 07:08:31 +05:30
Capa Bot
8cf74759a6 Sync capa rules submodule 2023-03-14 18:35:45 +00:00
Capa Bot
22a1a8e41f Sync capa rules submodule 2023-03-14 18:30:53 +00:00
Harsh Mehta
74009eb4a4 Updated Copyright (#1383)
* Updated Copyright
2023-03-14 17:58:43 +01:00
manasghandat
5932358f9d fix changes 2023-03-14 22:10:02 +05:30
manasghandat
1ad5364fec fix changes 2023-03-14 22:09:35 +05:30
Capa Bot
201330295c Sync capa rules submodule 2023-03-14 16:25:56 +00:00
mr-tz
a7b7f643a5 update translator and tests 2023-03-14 10:13:49 +01:00
Capa Bot
4fd6f17ced Sync capa rules submodule 2023-03-14 07:34:15 +00:00
dependabot[bot]
e67679658a build(deps-dev): bump mypy from 1.0.1 to 1.1.1
Bumps [mypy](https://github.com/python/mypy) from 1.0.1 to 1.1.1.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v1.0.1...v1.1.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-13 14:58:43 +00:00
manasghandat
d67f924b73 Merge branch 'master' of https://github.com/mandiant/capa 2023-03-12 17:41:45 +05:30
Willi Ballenthin
961daf6c36 Merge pull request #1366 from ggold7046/patch-1
Update profile-memory.py
2023-03-11 13:14:09 +01:00
Willi Ballenthin
748e7641ef Merge pull request #1367 from ggold7046/patch-3
Update match-function-id.py
2023-03-11 13:13:27 +01:00
AG
6321adc411 Update match-function-id.py
Updated with f string for enhanced readability.
2023-03-11 12:43:22 +05:30
AG
02e451a2b1 Update profile-memory.py
Updated with f string for enhanced readability.
2023-03-11 12:29:59 +05:30
Willi Ballenthin
8cac47038c Merge pull request #1354 from ggold7046/patch-1
Update import-to-bn.py
2023-03-10 17:18:21 +01:00
Willi Ballenthin
59ab8e0b04 Merge pull request #1356 from ggold7046/patch-3
Update import-to-ida.py
2023-03-10 17:17:59 +01:00
Willi Ballenthin
577d96c026 Merge pull request #1365 from linpeiyu164/master
fix wrong indentation level for args.backend
2023-03-10 17:17:22 +01:00
linpeiyu164
7031c68a85 fix wrong indentation level for args.backend 2023-03-11 00:07:24 +08:00
Willi Ballenthin
3a7326726e Merge pull request #1357 from ggold7046/patch-4
Update insn.py
2023-03-10 10:04:29 +01:00
Willi Ballenthin
f01d79df46 Merge pull request #1358 from ggold7046/patch-5
Update file.py
2023-03-10 10:04:00 +01:00
AG
df6de3446c Update file.py
Updated with f string for enhanced readability.
2023-03-10 13:10:02 +05:30
AG
eaeef59583 Update insn.py
Updated with f strings for enhanced readability.
2023-03-10 13:03:04 +05:30
manasghandat
f9c7ca2941 fix CI issue in tests 2023-03-10 10:34:17 +05:30
AG
50935372ca Update import-to-ida.py
Updated with f string for enhanced readability.
2023-03-10 01:36:17 +05:30
AG
d8f89d49d4 Update import-to-bn.py
Used f string for enhanced readability.
2023-03-10 01:17:59 +05:30
Zander Work
7e823057b9 Apply suggestions from code review
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-03-09 11:51:19 -05:00
manasghandat
e4d69984d3 Merge branch 'fstring' of https://github.com/manasghandat/capa into fstring 2023-03-09 22:04:13 +05:30
manasghandat
acd04e7181 Merge branch 'mandiant:master' into fstring 2023-03-09 22:03:42 +05:30
manasghandat
22a53bb1dc fix as per review 2023-03-09 22:01:52 +05:30
manasghandat
aaef16f51b Merge branch 'master' of https://github.com/manasghandat/capa into fstring 2023-03-09 22:00:37 +05:30
manasghandat
8613c88a60 update according to review 2023-03-09 21:59:16 +05:30
manasghandat
6070bd562e Update scripts/import-to-ida.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-03-09 21:21:14 +05:30
Willi Ballenthin
01c4ac822c Merge pull request #1344 from mandiant/fix/1333
explorer: improve embedded PE detection
2023-03-09 15:49:10 +01:00
manasghandat
05dbdd4473 code style: add fstrings 2023-03-09 17:19:34 +05:30
Xusheng
64323b394a Encode the path with utf8 and then convert to hex in find_binja_path 2023-03-09 16:32:21 +08:00
Xusheng
70f6f1cd03 Use the binja extractor to get functions/basic blocks/instructions when the feature extractor is executed alone 2023-03-09 16:01:51 +08:00
Xusheng
e9d4a23dad Do MLIL basic block look-up in get_basic_blocks to avoid a O(n^2) algorithm 2023-03-09 15:53:44 +08:00
mr-tz
3cdbc66375 refactor 2023-03-09 07:40:58 +01:00
manasghandat
5128638071 code style: update lint.py (#1352)
* code style: update lint.py
2023-03-09 07:28:47 +01:00
manasghandat
1f80791f8f code style: update lint.py with correct format 2023-03-08 21:19:14 +05:30
mr-tz
44d8e693b0 improve int/Integer handling 2023-03-08 16:06:57 +01:00
manasghandat
3bdc61f5ee code style: update lint.py 2023-03-08 20:02:33 +05:30
mr-tz
a7e4d265e2 convert rd meta to proto 2023-03-08 14:45:26 +01:00
Willi Ballenthin
0ac497ab59 Merge pull request #1346 from mandiant/dependabot/pip/tqdm-4.65.0
build(deps): bump tqdm from 4.64.1 to 4.65.0
2023-03-08 14:35:46 +01:00
Zander Work
dbb0200147 update changelog 2023-03-07 00:20:19 -05:00
Zander Work
ff7a93f364 show overriden format/os in output 2023-03-07 00:15:42 -05:00
Zander Work
8f6a660f3d initial support for os override 2023-03-07 00:11:33 -05:00
Xusheng
64c542502b Fix the placement of some imports 2023-03-07 11:30:35 +08:00
Xusheng
b4974a80bb Fix typo in OS name 2023-03-07 11:06:18 +08:00
Mike Hunhoff
95f23dafe5 Update CHANGELOG.md 2023-03-06 08:55:32 -07:00
Mike Hunhoff
02dc42154b Update CHANGELOG.md
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-03-06 08:53:57 -07:00
dependabot[bot]
4047780c08 build(deps): bump tqdm from 4.64.1 to 4.65.0
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.64.1 to 4.65.0.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.64.1...v4.65.0)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-06 14:59:16 +00:00
Xusheng
c648af2cb4 Select a different test file for the nzxor feature 2023-03-05 12:52:49 +08:00
Xusheng
4a698ffdff Add a Binary Ninja backend for capa 2023-03-05 12:52:49 +08:00
Xusheng
1babdb069f Update readme for generating rule cache 2023-03-04 18:46:36 +08:00
Xusheng
b49213bef6 Include the type of value when the value of a Number is unexpected 2023-03-04 18:46:36 +08:00
Xusheng
42e877671b Update gitignore for pipfile and cache folder 2023-03-04 18:46:36 +08:00
Mike Hunhoff
14c18727db update CHANGELOG 2023-03-03 09:55:45 -07:00
Mike Hunhoff
aacfcaaa23 explorer: improve embedded PE detection 2023-03-03 09:52:50 -07:00
Mike Hunhoff
9f3428e1c3 explorer: fix plugin exception when loaded under idat (#1341) 2023-03-02 13:42:43 -07:00
Moritz
52de09a032 Fix byte/string extraction and unit tests (#1339)
* Fix wrong expected results on string and bytes tests. Fix https://github.com/mandiant/capa/issues/1336

* Fix IDA insn/byte extractor checks wrong address. Fix https://github.com/mandiant/capa/issues/1327

* fix vivisect string check and tests

---------

Co-authored-by: Xusheng <xusheng@vector35.com>
2023-03-02 10:33:14 +01:00
Capa Bot
be6bb879f3 Sync capa rules submodule 2023-03-01 15:50:20 +00:00
Capa Bot
f7371c4a9f Sync capa rules submodule 2023-03-01 15:09:07 +00:00
Capa Bot
bd7cf8cdd1 Sync capa rules submodule 2023-02-28 10:41:07 +00:00
Willi Ballenthin
70b39cbd2c Merge pull request #1328 from mandiant/dependabot/pip/types-tabulate-0.9.0.1
build(deps-dev): bump types-tabulate from 0.9.0.0 to 0.9.0.1
2023-02-28 10:50:37 +01:00
dependabot[bot]
199a5cff4b build(deps-dev): bump types-tabulate from 0.9.0.0 to 0.9.0.1
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.9.0.0 to 0.9.0.1.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-27 14:59:14 +00:00
Capa Bot
501e213dce Sync capa rules submodule 2023-02-27 08:59:54 +00:00
Capa Bot
d663007e60 Sync capa rules submodule 2023-02-24 14:52:58 +00:00
Mike Hunhoff
a07ca443f0 update OS to match OS_ANY for all supported OSes (#1324) 2023-02-24 07:51:40 -07:00
Willi Ballenthin
84df8baa5f Merge pull request #1313 from mandiant/dependabot/pip/pyinstaller-5.8.0
build(deps-dev): bump pyinstaller from 5.7.0 to 5.8.0
2023-02-24 10:26:09 +01:00
Willi Ballenthin
241c0aeedd Merge pull request #1321 from mandiant/dependabot/pip/mypy-1.0.1
build(deps-dev): bump mypy from 0.991 to 1.0.1
2023-02-24 10:24:39 +01:00
Willi Ballenthin
ae85399193 Merge pull request #1320 from mandiant/dependabot/pip/pydantic-1.10.5
build(deps): bump pydantic from 1.10.4 to 1.10.5
2023-02-24 10:24:14 +01:00
Capa Bot
17f70bb87c Sync capa rules submodule 2023-02-23 08:47:24 +00:00
Capa Bot
7a1f2f4b3b Sync capa rules submodule 2023-02-22 19:24:48 +00:00
Capa Bot
599d3ac92c Sync capa rules submodule 2023-02-21 21:38:32 +00:00
Capa Bot
02f8e57e66 Sync capa rules submodule 2023-02-21 10:46:20 +00:00
dependabot[bot]
b6ac6d2959 build(deps-dev): bump mypy from 0.991 to 1.0.1
Bumps [mypy](https://github.com/python/mypy) from 0.991 to 1.0.1.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.991...v1.0.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-20 14:58:39 +00:00
dependabot[bot]
c681175685 build(deps): bump pydantic from 1.10.4 to 1.10.5
Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.10.4 to 1.10.5.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/v1.10.5/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v1.10.4...v1.10.5)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-20 14:58:27 +00:00
Capa Bot
5e600d02a8 Sync capa rules submodule 2023-02-20 08:05:09 +00:00
Capa Bot
b9edb6dbc9 Sync capa-testfiles submodule 2023-02-16 10:31:51 +00:00
Capa Bot
6e5302e5ec Sync capa rules submodule 2023-02-15 16:46:14 +00:00
Capa Bot
4b472c8564 Sync capa rules submodule 2023-02-15 15:16:41 +00:00
Capa Bot
4ccf6f0e69 Sync capa rules submodule 2023-02-15 10:57:23 +00:00
Capa Bot
eac3d8336d Sync capa-testfiles submodule 2023-02-15 10:56:23 +00:00
Capa Bot
53475c9643 Sync capa rules submodule 2023-02-15 10:55:49 +00:00
Willi Ballenthin
3c0361fd5c Merge pull request #1317 from mandiant/fix-loop-viv
fix loop detection corner case
2023-02-15 11:50:26 +01:00
mr-tz
0d14c168a4 fix loop detection corner case 2023-02-15 11:41:54 +01:00
Capa Bot
00ecfe7a80 Sync capa-testfiles submodule 2023-02-15 10:22:12 +00:00
Willi Ballenthin
fd64b2c5d5 Merge pull request #1315 from mandiant/typing-address
freeze: better type annotations for Address value
2023-02-14 15:05:31 +01:00
Willi Ballenthin
099cd868ae Merge branch 'wb-proto' of personal.github.com:mandiant/capa into wb-proto 2023-02-14 13:04:47 +01:00
Willi Ballenthin
3071394ef4 Update capa/render/proto/__init__.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-02-14 16:24:47 +01:00
Willi Ballenthin
d1b4e59e7d Update capa/render/proto/__init__.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-02-14 16:24:39 +01:00
Willi Ballenthin
50750a59d9 Merge branch 'master' of personal.github.com:mandiant/capa into wb-proto 2023-02-14 13:04:28 +01:00
Willi Ballenthin
e41afbee58 changelog 2023-02-14 13:04:05 +01:00
Willi Ballenthin
9ea2aca9cb test: proto: emit the schema json, too 2023-02-14 11:24:30 +01:00
Willi Ballenthin
c7ab89507e setup: fix dep spec 2023-02-14 11:02:28 +01:00
Willi Ballenthin
c197fd5086 proto: add type stubs for generate schema 2023-02-14 10:57:43 +01:00
Willi Ballenthin
b6e607f60e ci: ignore syntax, type checking for protobuf generated files 2023-02-14 10:26:05 +01:00
Willi Ballenthin
38d8b7f501 render: add initial proto generator 2023-02-14 10:02:12 +01:00
Willi Ballenthin
514b4929b3 freeze: better type annotations for Address value 2023-02-14 09:47:57 +01:00
dependabot[bot]
e8cef536f6 build(deps-dev): bump pyinstaller from 5.7.0 to 5.8.0
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 5.7.0 to 5.8.0.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v5.7.0...v5.8.0)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 14:59:26 +00:00
Capa Bot
4ea3475d2b Sync capa rules submodule 2023-02-13 09:50:39 +00:00
Capa Bot
15a276e3a5 Sync capa rules submodule 2023-02-13 09:47:05 +00:00
Capa Bot
f6e58ea212 Sync capa rules submodule 2023-02-10 10:08:30 +00:00
Capa Bot
1b191b5aea Sync capa-testfiles submodule 2023-02-10 08:52:58 +00:00
Moritz
c2346f41cb update to v5.0.0 (#1308) 2023-02-08 21:34:45 +01:00
Capa Bot
3f40f47104 Sync capa rules submodule 2023-02-08 08:57:54 +00:00
Capa Bot
3dfb7beb6b Sync capa rules submodule 2023-02-07 15:56:56 +00:00
Moritz
6a222a6139 Update black (#1307)
* build(deps-dev): bump black from 22.12.0 to 23.1.0

Bumps [black](https://github.com/psf/black) from 22.12.0 to 23.1.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.12.0...23.1.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* reformat black 23.1.0

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-07 15:50:15 +01:00
Capa Bot
b34864c55e Sync capa rules submodule 2023-02-07 14:49:39 +00:00
Capa Bot
26655315c7 Sync capa rules submodule 2023-02-07 14:48:39 +00:00
Capa Bot
8aaa8809e6 Sync capa-testfiles submodule 2023-02-07 11:21:49 +00:00
Capa Bot
cbac0e0d3b Sync capa rules submodule 2023-02-07 09:59:16 +00:00
Capa Bot
22b8c594b8 Sync capa-testfiles submodule 2023-02-06 20:47:00 +00:00
Capa Bot
7a8065b2bb Sync capa rules submodule 2023-02-06 17:13:11 +00:00
Capa Bot
6070479e0a Sync capa rules submodule 2023-02-06 17:12:33 +00:00
Moritz
fd70dc24df feat: store results to database and UI updates (#1292)
* feat: store results to database and UI updates

* feat: update result caching and UI

* use system rules cache and improve result cache validation

* improve buttons and status messages

* improve error messaging for invalid caches

---------

Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>
2023-02-06 16:37:19 +01:00
Capa Bot
8cb8cfdb46 Sync capa-testfiles submodule 2023-02-06 15:21:58 +00:00
Capa Bot
79f25ec0a3 Sync capa rules submodule 2023-02-06 14:15:55 +00:00
Capa Bot
2235417a25 Sync capa-testfiles submodule 2023-02-06 14:07:24 +00:00
Capa Bot
ce449790df Sync capa-testfiles submodule 2023-02-06 14:03:55 +00:00
Capa Bot
79e36ab11d Sync capa-testfiles submodule 2023-02-06 13:52:53 +00:00
Capa Bot
dde3abdfa0 Sync capa-testfiles submodule 2023-02-06 09:07:31 +00:00
Mike Hunhoff
7ea166f98c explorer: fix UnboundLocal errors and improve render match by function (#1302) 2023-02-02 12:33:30 -07:00
Capa Bot
faceca6fec Sync capa rules submodule 2023-02-02 08:12:15 +00:00
Capa Bot
6589b2044b Sync capa rules submodule 2023-02-01 15:29:00 +00:00
Capa Bot
f00e44aba6 Sync capa-testfiles submodule 2023-02-01 15:28:22 +00:00
Capa Bot
6591b574a0 Sync capa rules submodule 2023-02-01 14:13:20 +00:00
Moritz
ca91051d1a Fix string length >= 4 and remove bytes/string overlaps (#1298)
* fix min string length >= 4

* feat: don't extract bytes for strings
2023-02-01 14:53:16 +01:00
Capa Bot
29f24de5d5 Sync capa rules submodule 2023-02-01 09:10:08 +00:00
Capa Bot
2014c64732 Sync capa rules submodule 2023-02-01 09:09:30 +00:00
Moritz
b5c6cdeaa1 Update ATT&CK and MBC lint data (#1297)
* sort by ID

* update ATT&CK/MBC lint data via script
2023-02-01 09:56:10 +01:00
Moritz
bf7c569060 Delete hook-smda.py (#1296) 2023-01-30 10:15:56 +01:00
Capa Bot
bbc0afd083 Sync capa rules submodule 2023-01-27 08:56:49 +00:00
Capa Bot
8857f92f7c Sync capa rules submodule 2023-01-26 08:15:31 +00:00
Willi Ballenthin
70f568b1cc Merge pull request #1291 from mandiant/rules-cache
cache rule set across invocations of capa
2023-01-25 17:52:34 +01:00
Capa Bot
c586166006 Sync capa-testfiles submodule 2023-01-25 16:45:08 +00:00
Moritz
96f266ce5e ci: pin GitHub Actions versions (#1295) 2023-01-25 17:34:28 +01:00
Willi Ballenthin
e5549d6ce8 Update capa/ida/plugin/form.py 2023-01-25 16:47:01 +01:00
Capa Bot
b60717bb8c Sync capa rules submodule 2023-01-24 14:35:01 +00:00
Willi Ballenthin
83eefd343c Update scripts/capa2yara.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-01-24 15:33:37 +01:00
Moritz
03e8be6368 Create scorecard.yml (#1294) 2023-01-24 14:15:53 +01:00
Capa Bot
a58e9e4df3 Sync capa rules submodule 2023-01-23 13:53:42 +00:00
Moritz
0a78187c69 optimize tests to speed them up (#1287)
* optimize tests to speed them up

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2023-01-23 11:25:04 +01:00
Willi Ballenthin
61112c2527 lint: fix pbar counts 2023-01-21 20:16:49 +01:00
Willi Ballenthin
67cfefd2df main: get_rules: remove progress bar 2023-01-21 19:38:23 +01:00
Willi Ballenthin
3dfd16c033 main: fix ValueError 2023-01-21 19:30:15 +01:00
Willi Ballenthin
67b9d2e1c0 black 2023-01-21 19:28:15 +01:00
Willi Ballenthin
a076a0c44e main: further document get_rules 2023-01-21 19:24:20 +01:00
Willi Ballenthin
f152729c79 explorer: use main.get_rules and simplify cache 2023-01-21 19:10:50 +01:00
Willi Ballenthin
3c0e36d5d4 ruleset: record number of source rules loaded 2023-01-21 19:10:35 +01:00
Willi Ballenthin
887f37b72c main: get_rules: accept callback to update status 2023-01-21 19:10:02 +01:00
Willi Ballenthin
e30dd08dec cache: add doc 2023-01-21 18:20:14 +01:00
Willi Ballenthin
2d1bbeda0c Merge branch 'rules-cache' of personal.github.com:mandiant/capa into rules-cache 2023-01-21 18:14:42 +01:00
Willi Ballenthin
68603a9cc7 Update scripts/cache-ruleset.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-01-23 12:13:07 +01:00
Willi Ballenthin
6c83db9977 Update scripts/cache-ruleset.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-01-23 12:12:57 +01:00
Willi Ballenthin
6d16cafbc8 cache: handle invalid caches 2023-01-21 18:14:12 +01:00
Willi Ballenthin
e503cedd8f main: pbar: realize the list so it has a length 2023-01-21 17:31:57 +01:00
Willi Ballenthin
1a498d1afc main: fix reference error 2023-01-20 16:21:44 +01:00
Willi Ballenthin
33a46cc633 ci: cache the ruleset 2023-01-20 16:19:46 +01:00
Willi Ballenthin
b3b9ec11dd pyinstaller: package up the cache directory, too 2023-01-20 16:11:00 +01:00
Willi Ballenthin
a7afdec2e1 cache: accept cache_dir parameter 2023-01-20 16:10:41 +01:00
Willi Ballenthin
56a0bedac9 scripts: add tool to cache a ruleset to a directory 2023-01-20 15:50:17 +01:00
Willi Ballenthin
f451fe68e1 pep8/mypy 2023-01-20 15:42:22 +01:00
Willi Ballenthin
946816e377 cache: improve variable name 2023-01-20 15:26:17 +01:00
Willi Ballenthin
99af09fce5 main: revert wording change, which was just churn 2023-01-20 15:24:34 +01:00
Willi Ballenthin
0888e5ad69 main: more doc 2023-01-20 15:22:43 +01:00
Willi Ballenthin
c423ccec67 add tests for ruleset caching 2023-01-20 15:20:26 +01:00
Willi Ballenthin
03f72f498e cache: use zlib to reduce cache size 2023-01-20 15:20:10 +01:00
Willi Ballenthin
fbd7c566f4 cache: add more helpers
to enable better testing
2023-01-20 15:19:48 +01:00
Willi Ballenthin
e09d35bbb9 main: fix rule content decoding 2023-01-20 15:01:05 +01:00
Willi Ballenthin
e644775ad1 changelog 2023-01-20 14:52:47 +01:00
Willi Ballenthin
6ad471a914 Merge branch 'master' into rules-cache 2023-01-20 14:51:32 +01:00
Willi Ballenthin
476ffabae9 rules: cache the ruleset to disk
ref: #1212
2023-01-20 14:50:00 +01:00
Willi Ballenthin
4b7a9e149f rules: move to directory structure 2023-01-20 13:27:30 +01:00
Capa Bot
49c18bd83d Sync capa rules submodule 2023-01-20 12:15:23 +00:00
Capa Bot
67717761bd Sync capa rules submodule 2023-01-20 12:15:02 +00:00
Capa Bot
b10196cdac Sync capa rules submodule 2023-01-20 11:12:04 +00:00
Moritz
fa0ddba436 add format to global features and code refactors (#1284)
* refactor: get format handling

* add format to global features
2023-01-19 13:31:00 +01:00
Capa Bot
0fb3be359f Sync capa rules submodule 2023-01-19 12:12:41 +00:00
Capa Bot
26662e99de Sync capa rules submodule 2023-01-19 12:11:19 +00:00
Willi Ballenthin
5513d4ca43 viv: insn: string: handle viv bug around substrings (#1273)
* viv: insn: string: handle viv bug around substrings

closes #1271

* use minimum string length 4

* update overlapping string test and fixup vivisect elf analysis missing function

Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2023-01-19 13:02:53 +01:00
Capa Bot
2b07ec925c Sync capa rules submodule 2023-01-19 11:23:42 +00:00
Capa Bot
efb4c9d540 Sync capa rules submodule 2023-01-19 10:58:26 +00:00
Moritz
b8de9625ee fix: don't extract invalid calls from features (#1285) 2023-01-19 11:56:13 +01:00
Willi Ballenthin
607daa345e Merge pull request #1288 from mandiant/dependabot/pip/wcwidth-0.2.6
build(deps): bump wcwidth from 0.2.5 to 0.2.6
2023-01-19 11:43:35 +01:00
Capa Bot
35e6df6f6b Sync capa rules submodule 2023-01-18 15:10:43 +00:00
dependabot[bot]
cb1ef965d0 build(deps): bump wcwidth from 0.2.5 to 0.2.6
Bumps [wcwidth](https://github.com/jquast/wcwidth) from 0.2.5 to 0.2.6.
- [Release notes](https://github.com/jquast/wcwidth/releases)
- [Commits](https://github.com/jquast/wcwidth/compare/0.2.5...0.2.6)

---
updated-dependencies:
- dependency-name: wcwidth
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 14:03:54 +00:00
Capa Bot
2ab057a24d Sync capa rules submodule 2023-01-12 13:15:35 +00:00
Capa Bot
12f8588c03 Sync capa-testfiles submodule 2023-01-12 12:59:01 +00:00
Capa Bot
3571f35578 Sync capa rules submodule 2023-01-12 11:57:41 +00:00
Willi Ballenthin
803fe321d1 Merge pull request #1283 from mandiant/fix/issue-1282
better detect invalid rules
2023-01-12 12:56:25 +01:00
Willi Ballenthin
cf42670e97 Merge branch 'master' into fix/issue-1282 2023-01-12 12:31:11 +01:00
Willi Ballenthin
ac36b9d328 changelog 2023-01-12 10:39:36 +01:00
Willi Ballenthin
9a9f72f07a pep8 2023-01-12 10:38:52 +01:00
Willi Ballenthin
4b9a844c92 rules: catch invalid YAML exception 2023-01-12 10:38:26 +01:00
Moritz
a273ad31d4 make read consistent with file object behavior (#1281) 2023-01-11 17:17:04 +01:00
Willi Ballenthin
16f3164865 Merge pull request #1280 from mandiant/revert-1275-dependabot/pip/networkx-3.0
Revert "build(deps): bump networkx from 2.5.1 to 3.0"
2023-01-11 12:16:47 +01:00
Willi Ballenthin
5fb9de775f setup: document networkx dep version pin 2023-01-11 10:50:55 +01:00
Willi Ballenthin
05879dc02a Revert "build(deps): bump networkx from 2.5.1 to 3.0" 2023-01-11 10:49:04 +01:00
Willi Ballenthin
d5cb36151f Merge pull request #1275 from mandiant/dependabot/pip/networkx-3.0
build(deps): bump networkx from 2.5.1 to 3.0
2023-01-10 16:52:45 +01:00
Moritz
b6fd95c7b8 use positive error return code numbers (#1274) 2023-01-10 13:14:23 +01:00
Willi Ballenthin
8ce570cea7 Merge pull request #1276 from mandiant/dependabot/pip/termcolor-2.2.0
build(deps): bump termcolor from 2.1.1 to 2.2.0
2023-01-10 12:25:01 +01:00
Willi Ballenthin
5b82ed2fd9 Merge pull request #1270 from mandiant/fix/issue-1267
features: string: better __str__ embedded whitespace
2023-01-10 12:21:27 +01:00
Capa Bot
37a4dbf822 Sync capa rules submodule 2023-01-09 15:53:03 +00:00
dependabot[bot]
ef86160d88 build(deps): bump termcolor from 2.1.1 to 2.2.0
Bumps [termcolor](https://github.com/termcolor/termcolor) from 2.1.1 to 2.2.0.
- [Release notes](https://github.com/termcolor/termcolor/releases)
- [Changelog](https://github.com/termcolor/termcolor/blob/main/CHANGES.md)
- [Commits](https://github.com/termcolor/termcolor/compare/2.1.1...2.2.0)

---
updated-dependencies:
- dependency-name: termcolor
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 14:03:48 +00:00
dependabot[bot]
5f31bdbb3e build(deps): bump networkx from 2.5.1 to 3.0
Bumps [networkx](https://github.com/networkx/networkx) from 2.5.1 to 3.0.
- [Release notes](https://github.com/networkx/networkx/releases)
- [Commits](https://github.com/networkx/networkx/compare/networkx-2.5.1...networkx-3.0)

---
updated-dependencies:
- dependency-name: networkx
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 14:03:44 +00:00
Capa Bot
810e2d70d3 Sync capa rules submodule 2023-01-09 13:38:25 +00:00
Moritz
85dd065f91 only show first lib match to reduce vverbose output noise (#1266)
* only show first lib match to reduce vverbose output noise

* improve rendering and wording
2023-01-09 14:14:08 +01:00
Capa Bot
2a61e357de Sync capa rules submodule 2023-01-09 13:08:27 +00:00
Willi Ballenthin
e34fdfae1a mypy 2023-01-09 13:01:41 +01:00
Willi Ballenthin
58e94a35cb features: string: better __str__ embedded whitespace 2023-01-09 10:51:08 +01:00
Capa Bot
93acf9feb4 Sync capa rules submodule 2023-01-09 08:50:03 +00:00
Moritz
0362148989 Merge pull request #1265 from mandiant/fix/extractor-logic
fix logic error from smda backend removal
2023-01-06 09:54:52 +01:00
mr-tz
985ea5ebdc fix logic error from smda backend removal 2023-01-05 12:27:27 +01:00
Capa Bot
64ebf14256 Sync capa rules submodule 2023-01-05 10:55:44 +00:00
Willi Ballenthin
cfebe5a5ba Merge pull request #1264 from mandiant/fix/issue-1263
render: verbose: fix rendering of scopes
2023-01-05 11:54:59 +01:00
Willi Ballenthin
99e0e45bfc changelog 2023-01-05 11:38:51 +01:00
Willi Ballenthin
83845078a7 render: verbose: fix rendering of scopes
closes #1263
2023-01-05 11:36:52 +01:00
Capa Bot
7c102509bd Sync capa rules submodule 2023-01-05 09:59:07 +00:00
Capa Bot
1af90b9db3 Sync capa rules submodule 2023-01-05 09:55:12 +00:00
Mike Hunhoff
d4de650f90 explorer: improve exception handling (#1262) 2023-01-04 13:28:15 -07:00
Capa Bot
5de0324441 Sync capa rules submodule 2023-01-04 16:59:55 +00:00
Moritz
5fa2a87747 fix dotnet and pe format handling (#1256) 2023-01-04 17:46:51 +01:00
Moritz
68ef9d7858 validate rule meta (#1257)
* validate rule meta
2023-01-04 17:46:25 +01:00
Mike Hunhoff
a286e066d1 explorer: refactor rule generator caching and matching (#1251)
* explorer: refactor rule generator caching and matching

* fix #1246

* fix #1159
2023-01-04 08:50:52 -07:00
Willi Ballenthin
94a712b820 Merge pull request #1213 from mandiant/fix-1062
remove SMDA backend
2023-01-04 14:48:41 +01:00
Moritz
c8aa73ac18 Merge pull request #1253 from mandiant/dependabot/pip/pydantic-1.10.4
build(deps): bump pydantic from 1.10.2 to 1.10.4
2023-01-04 11:17:31 +01:00
Capa Bot
a74b8e6328 Sync capa-testfiles submodule 2023-01-04 09:09:57 +00:00
Willi Ballenthin
ff773695d0 Merge pull request #1260 from jsoref/spelling
Spelling
2023-01-04 08:58:21 +01:00
Josh Soref
c4ebb0a31d spelling: unescaped
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
f9b3d6304c spelling: uncommitted
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
1c85f530b1 spelling: objects
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
d65d7bcd7e spelling: notifications
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
c11633c5db spelling: minimum
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
ea0a708f35 spelling: interesting
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
00254b93dc spelling: instruction
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
6932df3564 spelling: import
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
9e3a48aa8d spelling: globally
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
6e17462bd0 spelling: github
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
d29e7e6f3a spelling: further
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
049e222e88 spelling: falls through
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
caef7812a3 spelling: disassembly
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:32:39 -05:00
Josh Soref
68efa7316b spelling: dictionary
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:25:22 -05:00
Josh Soref
5396d5f99e spelling: contiguous
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:25:22 -05:00
Josh Soref
4576cbd0a1 spelling: committing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:25:22 -05:00
Josh Soref
1fa9180fee spelling: beginning
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:25:22 -05:00
Josh Soref
801c80d7a2 spelling: alphanum
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-01-04 00:25:22 -05:00
mr-tz
eba1989c9f Merge branch 'master' into fix-1062 2023-01-03 18:46:41 +01:00
Mike Hunhoff
90591811df explorer: improve rules error messaging and documentation (#1249) 2023-01-03 09:09:05 -07:00
Capa Bot
c959506ae9 Sync capa rules submodule 2023-01-03 14:58:40 +00:00
Moritz
25f9029a82 Merge pull request #1255 from mandiant/ci/update-actions
update Actions
2023-01-03 11:56:58 +01:00
Capa Bot
4f75b3d9f6 Sync capa rules submodule 2023-01-03 10:46:49 +00:00
Capa Bot
974d79f2be Sync capa rules submodule 2023-01-03 10:42:41 +00:00
mr-tz
c0a8a91281 update Actions 2023-01-03 11:39:51 +01:00
Capa Bot
2219139605 Sync capa-testfiles submodule 2023-01-03 10:20:18 +00:00
Capa Bot
966e38babf Sync capa rules submodule 2023-01-03 10:19:17 +00:00
Capa Bot
5f39083df6 Sync capa-testfiles submodule 2023-01-03 10:17:36 +00:00
Capa Bot
565b002bfe Sync capa rules submodule 2023-01-02 17:33:19 +00:00
Capa Bot
1dd5a8dbf2 Sync capa rules submodule 2023-01-02 17:31:53 +00:00
dependabot[bot]
7ef17b8dee build(deps): bump pydantic from 1.10.2 to 1.10.4
Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.10.2 to 1.10.4.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/v1.10.4/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v1.10.2...v1.10.4)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-02 14:05:03 +00:00
Moritz
d01a0e022d Merge pull request #1248 from mandiant/dependabot/pip/isort-5.11.4
build(deps-dev): bump isort from 5.11.3 to 5.11.4
2023-01-02 13:22:31 +01:00
Moritz
3258556d5d Merge pull request #1247 from mandiant/doc/rule-compat-info
update rule compatibility doc
2023-01-02 13:21:53 +01:00
Mike Hunhoff
5f77200108 explorer: assume 32-bit displacement for offsets (#1250)
* explorer: assume 32-bit displacement for offsets
2022-12-29 07:08:10 -07:00
dependabot[bot]
b12865f1e5 build(deps-dev): bump isort from 5.11.3 to 5.11.4
Bumps [isort](https://github.com/pycqa/isort) from 5.11.3 to 5.11.4.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.11.3...5.11.4)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 14:04:30 +00:00
mr-tz
ee90fc8761 update rule compatibility doc 2022-12-23 18:30:25 +01:00
Moritz
e6585ee526 Merge pull request #1245 from mandiant/doc/rule-releases
simplified rule release guidance
2022-12-22 15:37:06 +01:00
Mike Hunhoff
b68be0c2ce dotnet: emit namespace/class features for type references (#1242)
* dotnet: emit namespace/class features for type references

* dotnet: pre-compute .NET token caches
2022-12-21 15:59:29 -07:00
mr-tz
3b95ed0b5a simplified rule release guidance 2022-12-21 16:03:05 +01:00
Mike Hunhoff
50490e6a93 dotnet: emit namespace/class features for ldvirtftn/ldftn instructions (#1241)
* dotnet: emit namespace/class features for ldvirtftn/ldftn instructions

* dotnet: add unit tests for ldftn/ldvirtftn namespace/class features
2022-12-20 13:29:29 -07:00
Willi Ballenthin
d466345e4e Merge pull request #1239 from mandiant/dependabot/pip/isort-5.11.3
build(deps-dev): bump isort from 5.10.1 to 5.11.3
2022-12-20 13:42:24 +01:00
Mike Hunhoff
4ece47c64c dotnet: emit calls to/from MethodDef methods (#1236)
* dotnet: emit calls to/from MethodDef methods

* dotnet: update function.py copyright header
2022-12-19 15:06:16 -07:00
Moritz
2b85af0f88 explorer: update and remove outdated documentation (#1238) 2022-12-19 14:53:16 -07:00
Mike Hunhoff
e0491097b0 dotnet: emit API features for generic methods (#1231)
* dotnet: emit API features for generic methods

* dotnet: improve type checking

* dotnet: emit namespace/class features for generic methods

* dotnet: update for dnfile 0.13.0

* dotnet: refactor property extraction
2022-12-19 14:45:21 -07:00
dependabot[bot]
fa3d658f33 build(deps): bump dnfile from 0.12.0 to 0.13.0 (#1240)
Bumps [dnfile](https://github.com/malwarefrank/dnfile) from 0.12.0 to 0.13.0.
- [Release notes](https://github.com/malwarefrank/dnfile/releases)
- [Changelog](https://github.com/malwarefrank/dnfile/blob/master/HISTORY.rst)
- [Commits](https://github.com/malwarefrank/dnfile/compare/v0.12.0...v0.13.0)

---
updated-dependencies:
- dependency-name: dnfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-19 10:43:54 -07:00
dependabot[bot]
6dcd115765 build(deps-dev): bump isort from 5.10.1 to 5.11.3
Bumps [isort](https://github.com/pycqa/isort) from 5.10.1 to 5.11.3.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.10.1...5.11.3)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 14:02:58 +00:00
Willi Ballenthin
88cffee902 ci: bump action versions (#1233)
* ci: bump action versions

Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2022-12-19 12:34:18 +01:00
Willi Ballenthin
b12d526a60 tests: use python 3.11 (#1191) 2022-12-19 11:12:42 +01:00
Mike Hunhoff
3af7fe0b08 dotnet: address unhandled exceptions through improved type checking (#1230)
* dotnet: bump dncil version

* dotnet: check #US stream valid before access

* dotnet: use assert statements to guard types
2022-12-15 12:55:57 -07:00
Willi Ballenthin
d7548c0b20 Merge pull request #1229 from mandiant/williballenthin-patch-2
setup: viv-utils 0.7.7
2022-12-15 12:03:48 +01:00
Willi Ballenthin
f79e16d1a6 Merge branch 'master' of https://github.com/mandiant/capa into williballenthin-patch-2 2022-12-15 10:07:36 +00:00
Willi Ballenthin
ad47ea3bab Merge pull request #1235 from mandiant/fix/issue-1234
stricter mypy checking
2022-12-15 10:54:03 +01:00
Willi Ballenthin
505910edb5 dotnet: remove duplicative validate_has_dotnet helper 2022-12-14 21:28:32 +01:00
Willi Ballenthin
aee0ec8016 features: cleanup mypy checking 2022-12-14 21:22:52 +01:00
Willi Ballenthin
613c185428 tests: fix broken test 2022-12-14 11:51:25 +01:00
Willi Ballenthin
501227f23f elf: fix missing attribute 2022-12-14 11:14:01 +01:00
Willi Ballenthin
56d075fd32 typing 2022-12-14 11:08:46 +01:00
Willi Ballenthin
9ae908c741 elf: better format attribution declarations 2022-12-14 10:57:27 +01:00
Willi Ballenthin
81500a4d1d black 2022-12-14 10:48:00 +01:00
Willi Ballenthin
b819033da0 lots of mypy 2022-12-14 10:37:39 +01:00
Willi Ballenthin
35243ef7a6 changelog 2022-12-13 13:23:46 +00:00
Willi Ballenthin
655c45d43f Merge pull request #1226 from mandiant/dependabot/pip/pycodestyle-2.10.0
build(deps-dev): bump pycodestyle from 2.9.1 to 2.10.0
2022-12-13 14:15:58 +01:00
Willi Ballenthin
34c4809f68 Merge pull request #1228 from mandiant/dependabot/pip/pyinstaller-5.7.0
build(deps-dev): bump pyinstaller from 5.5 to 5.7.0
2022-12-13 14:15:46 +01:00
dependabot[bot]
f9b6800831 build(deps-dev): bump pycodestyle from 2.9.1 to 2.10.0
Bumps [pycodestyle](https://github.com/PyCQA/pycodestyle) from 2.9.1 to 2.10.0.
- [Release notes](https://github.com/PyCQA/pycodestyle/releases)
- [Changelog](https://github.com/PyCQA/pycodestyle/blob/main/CHANGES.txt)
- [Commits](https://github.com/PyCQA/pycodestyle/compare/2.9.1...2.10.0)

---
updated-dependencies:
- dependency-name: pycodestyle
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-13 13:15:33 +00:00
Willi Ballenthin
b5254e3662 Merge pull request #1227 from mandiant/dependabot/pip/mypy-0.991
build(deps-dev): bump mypy from 0.982 to 0.991
2022-12-13 14:15:07 +01:00
Willi Ballenthin
148cb71839 Merge pull request #1225 from mandiant/dependabot/pip/black-22.12.0
build(deps-dev): bump black from 22.10.0 to 22.12.0
2022-12-13 14:14:23 +01:00
Willi Ballenthin
62700ca5d1 setup: bump viv-utils to 0.7.7 for py3.11 support 2022-12-13 14:07:51 +01:00
Willi Ballenthin
b1d6fcd6c8 mypy 2022-12-13 13:20:24 +01:00
Willi Ballenthin
8afebc1f17 ci: mypy: enable --check-untyped-defs 2022-12-13 13:20:01 +01:00
Mike Hunhoff
447cd95bc5 ida: add support for COFF and extern functions (#1223) 2022-12-12 16:36:44 -07:00
Willi Ballenthin
5224380947 setup: viv-utils 0.7.6
closes #1192
2022-12-12 18:02:07 +01:00
Moritz
7aeb685412 Merge pull request #1224 from mandiant/williballenthin-patch-2
tests: os: fix test
2022-12-12 16:43:58 +01:00
Capa Bot
b6911f8ad2 Sync capa rules submodule 2022-12-12 14:39:26 +00:00
dependabot[bot]
a7d06275c1 build(deps-dev): bump pyinstaller from 5.5 to 5.7.0
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 5.5 to 5.7.0.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v5.5...v5.7.0)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 14:02:58 +00:00
dependabot[bot]
d581eefcdf build(deps-dev): bump mypy from 0.982 to 0.991
Bumps [mypy](https://github.com/python/mypy) from 0.982 to 0.991.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.982...v0.991)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 14:02:53 +00:00
dependabot[bot]
47f58162c5 build(deps-dev): bump black from 22.10.0 to 22.12.0
Bumps [black](https://github.com/psf/black) from 22.10.0 to 22.12.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.10.0...22.12.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 14:02:41 +00:00
Willi Ballenthin
ee72ed4b53 tests: os: fix test 2022-12-12 14:06:17 +01:00
Capa Bot
5cd7f33d00 Sync capa-testfiles submodule 2022-12-12 12:29:44 +00:00
Willi Ballenthin
d6674c7548 Merge pull request #1222 from mandiant/fix/issue-1221
elf: better detect linux ELF files
2022-12-12 13:28:59 +01:00
Capa Bot
a46d7b3262 Sync capa-testfiles submodule 2022-12-12 12:18:01 +00:00
Willi Ballenthin
0f902124d1 elf: reduce logging verbosity 2022-12-12 11:43:48 +01:00
Willi Ballenthin
d4a218e268 elf: os: bug fixes 2022-12-12 11:41:01 +01:00
Willi Ballenthin
22bef146f8 tests: add OS detection tests 2022-12-12 11:40:43 +01:00
Willi Ballenthin
b26ed47ab8 tests: add OS detection tests 2022-12-12 11:40:32 +01:00
Willi Ballenthin
7ba08edffa changelog 2022-12-09 16:09:41 +01:00
Willi Ballenthin
c958a6a286 elf: black 2022-12-09 16:07:46 +01:00
William Ballenthin
1583fedba2 mypy 2022-12-09 17:34:44 +01:00
William Ballenthin
307a6fad4f elf: os: detect via so dependencies 2022-12-09 14:31:03 +01:00
William Ballenthin
958d5bcc6a elf: refactor OS detection 2022-12-09 12:56:09 +01:00
William Ballenthin
c5a9aa21bf wip: elf: better detect linux ELF files 2022-12-08 21:33:57 +01:00
Willi Ballenthin
13b5d7c179 Merge pull request #1220 from mandiant/disable-smda-tests
skip smda tests until we remove the backend
2022-12-08 12:07:16 +01:00
Capa Bot
bd84ee83a5 Sync capa rules submodule 2022-12-07 19:10:53 +00:00
mr-tz
97f633312f skip smda tests until we remove the backend 2022-12-07 16:44:52 +01:00
Willi Ballenthin
b290690b19 Merge pull request #1216 from mandiant/fix/issue-1215
add missing vverbose feature renderers
2022-12-07 15:12:10 +01:00
Willi Ballenthin
fc57ed76a0 Merge pull request #1218 from mandiant/fix/issue-1194
small explorer fixes
2022-12-07 15:11:02 +01:00
Willi Ballenthin
a6fdb71178 utils: use a single hex() implementation 2022-12-07 14:09:37 +00:00
Willi Ballenthin
fe2f668306 CHANGELOG 2022-12-07 13:41:10 +00:00
Willi Ballenthin
45d007fa9a explorer: fix UnboundLocalError
closes #1217
2022-12-07 13:39:55 +00:00
Willi Ballenthin
662ec11031 explorer: accept only plaintext to rule window
closes #1194
2022-12-07 13:38:50 +00:00
Willi Ballenthin
1d8a3486cd vverbose: prefer isinstance checks over strings
which also makes mypy happier
2022-12-07 13:14:05 +00:00
Willi Ballenthin
c195afa0b3 explorer: improve rendering of operand number/offsets 2022-12-07 13:07:24 +00:00
Willi Ballenthin
63e0d9b3f3 vverbose: render offer and operand number/offset features
closes #1215
2022-12-07 12:59:37 +00:00
Willi Ballenthin
659cbedc3c vverbose: dont show offset for format 2022-12-07 12:59:21 +00:00
Willi Ballenthin
0ebba2cd15 vverbose: guard against rendering basic blocks 2022-12-07 12:58:55 +00:00
Willi Ballenthin
1f091a4ccd tests: add tests demonstrating vverbose feature rendering 2022-12-07 12:58:10 +00:00
Willi Ballenthin
d1aafa3764 vverbose: render offset
closes #1215
2022-12-07 11:52:41 +00:00
Willi Ballenthin
faefe41ad5 Merge pull request #1214 from mandiant/fix/pylint-fixes
pylint fixes
2022-12-07 12:41:57 +01:00
Willi Ballenthin
473d0daf58 render: pylint 2022-12-07 11:41:05 +00:00
Willi Ballenthin
a10abfebde main: pylint 2022-12-06 16:23:10 +00:00
Willi Ballenthin
78172b5f5b rules: pylint 2022-12-06 16:06:08 +00:00
Willi Ballenthin
1caeb248ca pylint: fix old-style super calls 2022-12-06 16:02:21 +00:00
Willi Ballenthin
8527d02dc8 pylint fixes 2022-12-06 15:37:31 +00:00
Willi Ballenthin
0e73f26e88 CHANGELOG 2022-12-06 15:34:22 +00:00
Willi Ballenthin
ed24db4460 extractors: remove SMDA backend
closes #1210
closes #1062
2022-12-06 15:33:17 +00:00
Willi Ballenthin
127886144b Merge pull request #1209 from mandiant/williballenthin-patch-3
import-to-ida: use other md5 function
2022-12-06 13:07:35 +01:00
Willi Ballenthin
c83877ec74 mypy: ignore ida_nalt 2022-12-06 12:06:07 +00:00
Willi Ballenthin
8d6fcd9939 Merge pull request #1208 from mandiant/williballenthin-patch-2
import-to-ida: fix append comment
2022-12-06 13:03:55 +01:00
Willi Ballenthin
1dc5e40308 Merge pull request #1206 from mandiant/dependabot/pip/termcolor-2.1.1
build(deps): bump termcolor from 2.0.1 to 2.1.1
2022-12-06 12:58:04 +01:00
Willi Ballenthin
cc832d26aa import-to-ida: fix imports 2022-12-05 15:27:22 +00:00
Willi Ballenthin
9fcb70387d import-to-ida: use other md5 function
ref #1204
2022-12-05 16:17:11 +01:00
Willi Ballenthin
236ad883d4 changelog 2022-12-05 15:13:16 +00:00
Willi Ballenthin
12c9c466c7 import-to-ida: fix append comment
ref #1204
2022-12-05 16:02:40 +01:00
dependabot[bot]
5a1cb0e48d build(deps): bump termcolor from 2.0.1 to 2.1.1
Bumps [termcolor](https://github.com/termcolor/termcolor) from 2.0.1 to 2.1.1.
- [Release notes](https://github.com/termcolor/termcolor/releases)
- [Changelog](https://github.com/termcolor/termcolor/blob/main/CHANGES.md)
- [Commits](https://github.com/termcolor/termcolor/compare/2.0.1...2.1.1)

---
updated-dependencies:
- dependency-name: termcolor
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 14:03:10 +00:00
Capa Bot
5196caabb5 Sync capa rules submodule 2022-11-22 12:35:27 +00:00
Capa Bot
0f99592903 Sync capa-testfiles submodule 2022-11-08 19:58:11 +00:00
Capa Bot
56e9645700 Sync capa rules submodule 2022-10-24 18:28:08 +00:00
Capa Bot
0d8c6cc0fd Sync capa rules submodule 2022-10-13 14:37:09 +00:00
Mike Hunhoff
20c7949be3 dotnet: emit features from newobj instruction (#1186) 2022-10-13 08:35:29 -06:00
Willi Ballenthin
7cc6773bf8 Merge pull request #1185 from mandiant/dependabot/pip/pyinstaller-5.5
build(deps-dev): bump pyinstaller from 5.4.1 to 5.5
2022-10-11 15:56:11 +02:00
Willi Ballenthin
055700a5d1 Merge pull request #1182 from mandiant/dependabot/pip/mypy-0.982
build(deps-dev): bump mypy from 0.971 to 0.982
2022-10-11 15:55:37 +02:00
Willi Ballenthin
85b14075cd address: explicitly resolve hash from int 2022-10-11 09:47:25 +00:00
Willi Ballenthin
149c3989f1 Merge pull request #1178 from mandiant/dependabot/pip/pytest-cov-4.0.0
build(deps-dev): bump pytest-cov from 3.0.0 to 4.0.0
2022-10-11 10:58:49 +02:00
dependabot[bot]
3b5a34f331 build(deps-dev): bump mypy from 0.971 to 0.982
Bumps [mypy](https://github.com/python/mypy) from 0.971 to 0.982.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.971...v0.982)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-11 06:18:59 +00:00
dependabot[bot]
b4fe2d8592 build(deps-dev): bump pytest-cov from 3.0.0 to 4.0.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 3.0.0 to 4.0.0.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v3.0.0...v4.0.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-11 06:18:47 +00:00
Moritz
67d06c73e0 Merge pull request #1183 from mandiant/dependabot/pip/types-tabulate-0.9.0.0
build(deps-dev): bump types-tabulate from 0.8.9 to 0.9.0.0
2022-10-11 08:18:21 +02:00
dependabot[bot]
81a942d7a1 build(deps-dev): bump pyinstaller from 5.4.1 to 5.5
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 5.4.1 to 5.5.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v5.4.1...v5.5)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-11 06:18:13 +00:00
Moritz
521473cd81 Merge pull request #1184 from mandiant/dependabot/pip/black-22.10.0
build(deps-dev): bump black from 22.8.0 to 22.10.0
2022-10-11 08:18:02 +02:00
Moritz
676d422511 Merge pull request #1181 from mandiant/dependabot/pip/tabulate-0.9.0
build(deps): bump tabulate from 0.8.9 to 0.9.0
2022-10-11 08:17:45 +02:00
dependabot[bot]
f2dbb531fe build(deps-dev): bump black from 22.8.0 to 22.10.0
Bumps [black](https://github.com/psf/black) from 22.8.0 to 22.10.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.8.0...22.10.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-10 15:09:31 +00:00
dependabot[bot]
84fce86152 build(deps-dev): bump types-tabulate from 0.8.9 to 0.9.0.0
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.9 to 0.9.0.0.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-10 15:09:24 +00:00
dependabot[bot]
8307c66256 build(deps): bump tabulate from 0.8.9 to 0.9.0
Bumps [tabulate](https://github.com/astanin/python-tabulate) from 0.8.9 to 0.9.0.
- [Release notes](https://github.com/astanin/python-tabulate/releases)
- [Changelog](https://github.com/astanin/python-tabulate/blob/master/CHANGELOG)
- [Commits](https://github.com/astanin/python-tabulate/compare/v0.8.9...v0.9.0)

---
updated-dependencies:
- dependency-name: tabulate
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-10 15:09:17 +00:00
Capa Bot
ac71676d79 Sync capa rules submodule 2022-10-07 15:40:27 +00:00
Capa Bot
70e6d83259 Sync capa rules submodule 2022-10-03 15:28:44 +00:00
Capa Bot
3bbac4a35f Sync capa rules submodule 2022-10-03 15:17:03 +00:00
Capa Bot
87455ed6dd Sync capa-testfiles submodule 2022-09-20 19:34:29 +00:00
Mike Hunhoff
e1735f0a5e update pydantic models to guarantee type coercion (#1176)
* add CompoundStatement to fix Pydantic typing bug

* explorer: fix #1151

* explorer: support rendering operand number/offset
2022-09-20 08:38:19 -06:00
Capa Bot
8521f85742 Sync capa-testfiles submodule 2022-09-19 14:26:32 +00:00
Moritz
b1b15e2eef fix: do not overwrite __version__ (#1170) 2022-09-14 14:45:58 -06:00
Moritz
36e304839b Merge pull request #1173 from mandiant/dependabot/pip/pydantic-1.10.2
build(deps): bump pydantic from 1.10.1 to 1.10.2
2022-09-14 17:40:21 +02:00
Moritz
5a14a6d0cc Merge pull request #1172 from mandiant/dependabot/pip/termcolor-2.0.1
build(deps): bump termcolor from 1.1.0 to 2.0.1
2022-09-14 17:40:07 +02:00
Moritz
85901893a0 Merge pull request #1171 from mandiant/dependabot/pip/pyinstaller-5.4.1
build(deps-dev): bump pyinstaller from 5.3 to 5.4.1
2022-09-14 17:39:55 +02:00
dependabot[bot]
49d7f2a88f build(deps): bump pydantic from 1.10.1 to 1.10.2
Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.10.1 to 1.10.2.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v1.10.1...v1.10.2)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-12 14:17:04 +00:00
dependabot[bot]
8d8c5f99c1 build(deps): bump termcolor from 1.1.0 to 2.0.1
Bumps [termcolor](https://github.com/termcolor/termcolor) from 1.1.0 to 2.0.1.
- [Release notes](https://github.com/termcolor/termcolor/releases)
- [Changelog](https://github.com/termcolor/termcolor/blob/main/CHANGES.md)
- [Commits](https://github.com/termcolor/termcolor/compare/1.1.0...2.0.1)

---
updated-dependencies:
- dependency-name: termcolor
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-12 14:17:00 +00:00
dependabot[bot]
4069515cad build(deps-dev): bump pyinstaller from 5.3 to 5.4.1
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 5.3 to 5.4.1.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v5.3...v5.4.1)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-12 14:16:54 +00:00
Mike Hunhoff
3c1cd67f60 dotnet: support property feature extraction (#1168) 2022-09-09 12:09:41 -06:00
Capa Bot
580948e46b Sync capa rules submodule 2022-09-09 11:21:24 +00:00
Capa Bot
4ffd7b89f3 Sync capa rules submodule 2022-09-09 11:19:59 +00:00
Moritz
2441c18a85 fix: use int instead of Token to decouple extractor and features (#1158) 2022-09-08 11:09:17 -06:00
Moritz
ee89fa45b6 Update build.yml (#1157) 2022-09-08 10:58:29 -06:00
Moritz
3976e5858d feat: verify rule metadata format on load (#1160) 2022-09-08 10:56:59 -06:00
Capa Bot
4e542f9cff Sync capa rules submodule 2022-09-08 08:42:53 +00:00
Moritz
ce1ecfad4d Merge pull request #1164 from mandiant/dependabot/pip/psutil-5.9.2
build(deps-dev): bump psutil from 5.9.1 to 5.9.2
2022-09-06 17:40:59 +02:00
dependabot[bot]
d9d5aaffa1 build(deps-dev): bump psutil from 5.9.1 to 5.9.2
Bumps [psutil](https://github.com/giampaolo/psutil) from 5.9.1 to 5.9.2.
- [Release notes](https://github.com/giampaolo/psutil/releases)
- [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst)
- [Commits](https://github.com/giampaolo/psutil/compare/release-5.9.1...release-5.9.2)

---
updated-dependencies:
- dependency-name: psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-06 06:53:53 +00:00
Moritz
21809350f7 Merge pull request #1166 from mandiant/dependabot/pip/pydantic-1.10.1
build(deps): bump pydantic from 1.9.2 to 1.10.1
2022-09-06 08:53:46 +02:00
Moritz
418b063067 Merge pull request #1165 from mandiant/dependabot/pip/tqdm-4.64.1
build(deps): bump tqdm from 4.64.0 to 4.64.1
2022-09-06 08:53:30 +02:00
Moritz
dcf838872c Merge pull request #1163 from mandiant/dependabot/pip/pytest-7.1.3
build(deps-dev): bump pytest from 7.1.2 to 7.1.3
2022-09-06 08:53:07 +02:00
Moritz
456b32e6a8 Merge pull request #1162 from mandiant/dependabot/pip/black-22.8.0
build(deps-dev): bump black from 22.6.0 to 22.8.0
2022-09-06 08:52:51 +02:00
dependabot[bot]
acad9c5570 build(deps): bump pydantic from 1.9.2 to 1.10.1
Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.9.2 to 1.10.1.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v1.9.2...v1.10.1)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-05 16:32:53 +00:00
dependabot[bot]
4b2cfb4825 build(deps): bump tqdm from 4.64.0 to 4.64.1
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.64.0 to 4.64.1.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.64.0...v4.64.1)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-05 16:32:49 +00:00
dependabot[bot]
7733562587 build(deps-dev): bump pytest from 7.1.2 to 7.1.3
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.2 to 7.1.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.1.2...7.1.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-05 16:32:34 +00:00
dependabot[bot]
eaa70fa80f build(deps-dev): bump black from 22.6.0 to 22.8.0
Bumps [black](https://github.com/psf/black) from 22.6.0 to 22.8.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.6.0...22.8.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-05 16:32:26 +00:00
Capa Bot
44843ea977 Sync capa rules submodule 2022-08-29 16:50:20 +00:00
Capa Bot
cac041b869 Sync capa-testfiles submodule 2022-08-24 10:47:31 +00:00
Moritz
49684e4c25 fix: display instruction items (#1155)
* fix: display instruction items

* fix: instruction item format
2022-08-23 17:12:51 +02:00
Mike Hunhoff
47268c2344 render: convert feature attributes to aliased dictionary for vverbose (#1152) 2022-08-18 12:15:52 -06:00
Moritz
da0a1e7903 Merge pull request #1149 from gdesmar/master
Fix maec.malware_category_ov typo in vverbose render
2022-08-18 11:31:40 +02:00
Moritz
eca1582678 Merge pull request #1148 from idiom/master
Add Optional attribute to argv property in Metadata model.
2022-08-18 11:31:23 +02:00
gdesmar
2049058b45 render: vverbose, fix maec.malware_category_ov typo 2022-08-16 18:40:51 +00:00
Moritz
c2b5e7116d Merge pull request #1146 from mandiant/dependabot/pip/dnfile-0.12.0
build(deps): bump dnfile from 0.11.0 to 0.12.0
2022-08-16 11:06:15 +02:00
dependabot[bot]
9c1b076a5f build(deps): bump dnfile from 0.11.0 to 0.12.0
Bumps [dnfile](https://github.com/malwarefrank/dnfile) from 0.11.0 to 0.12.0.
- [Release notes](https://github.com/malwarefrank/dnfile/releases)
- [Changelog](https://github.com/malwarefrank/dnfile/blob/master/HISTORY.rst)
- [Commits](https://github.com/malwarefrank/dnfile/compare/v0.11.0...v0.12.0)

---
updated-dependencies:
- dependency-name: dnfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-16 08:14:55 +00:00
Moritz
51f7e10cb6 Merge pull request #1145 from mandiant/dependabot/pip/pyelftools-0.29
build(deps): bump pyelftools from 0.28 to 0.29
2022-08-16 10:14:24 +02:00
Moritz
25ad6446ba Merge pull request #1144 from mandiant/dependabot/pip/pydantic-1.9.2
build(deps): bump pydantic from 1.9.1 to 1.9.2
2022-08-16 10:14:04 +02:00
idiom
1af5255501 Add Optional attribute to argv property in Metadata model. This resovles issue where a ValidationError is raised when argv is not in the passed matedata and set to None in from_capa. 2022-08-15 15:55:19 -04:00
dependabot[bot]
49d61db8f9 build(deps): bump pyelftools from 0.28 to 0.29
Bumps [pyelftools](https://github.com/eliben/pyelftools) from 0.28 to 0.29.
- [Release notes](https://github.com/eliben/pyelftools/releases)
- [Changelog](https://github.com/eliben/pyelftools/blob/master/CHANGES)
- [Commits](https://github.com/eliben/pyelftools/compare/v0.28...v0.29)

---
updated-dependencies:
- dependency-name: pyelftools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 14:23:21 +00:00
dependabot[bot]
601471c1e6 build(deps): bump pydantic from 1.9.1 to 1.9.2
Bumps [pydantic](https://github.com/samuelcolvin/pydantic) from 1.9.1 to 1.9.2.
- [Release notes](https://github.com/samuelcolvin/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/master/HISTORY.md)
- [Commits](https://github.com/samuelcolvin/pydantic/compare/v1.9.1...v1.9.2)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 14:23:17 +00:00
Moritz
3c4141589d Release v4.0.1 (#1143)
* update scripts/lint.py to validate rule metadata using pydantic (#1141)

* doc: v401

Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>
2022-08-15 13:26:39 +02:00
Moritz
c5f768accc Update document and version set in PyInstaller (#1140)
* doc: update v4 resources

* tmp

* fix: set version #1136

* format: black

* comment version substring replacement
2022-08-15 11:10:17 +02:00
Capa Bot
2e6671ff91 Sync capa rules submodule 2022-08-15 08:39:57 +00:00
Capa Bot
f4171c32cf Sync capa-testfiles submodule 2022-08-15 08:31:20 +00:00
Mike Hunhoff
449c64d80b update scripts/lint.py to validate rule metadata using pydantic (#1141) 2022-08-12 08:26:39 -06:00
Capa Bot
735cb57b10 Sync capa rules submodule 2022-08-12 09:29:53 +00:00
Moritz
81cb4b31e1 Release v4.0.0 (#1105)
* release: v4 prep

* add SMDA deprecation warning

* doc: update v4 changes

* Update CHANGELOG.md

* Update CHANGELOG.md

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

* doc: add DeprecationWarning

* fix: add __index__ method

* ci: test build run on more OSs

* explorer: update supported versions to include IDA 8.0

Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2022-08-10 15:32:52 +02:00
Capa Bot
e564466ac8 Sync capa rules submodule 2022-08-09 10:50:59 +00:00
Capa Bot
63e0d903c7 Sync capa rules submodule 2022-08-09 10:35:39 +00:00
Moritz
dbc1ddcd7b Merge pull request #1133 from mandiant/dependabot/pip/smda-1.8.4
build(deps): bump smda from 1.7.4 to 1.8.4
2022-08-09 12:34:32 +02:00
Moritz
a00d0d5222 Merge pull request #1128 from mandiant/dependabot/pip/pyinstaller-5.3
build(deps-dev): bump pyinstaller from 5.2 to 5.3
2022-08-09 12:33:59 +02:00
Moritz
428d125340 Merge pull request #1132 from mandiant/dependabot/pip/pycodestyle-2.9.1
build(deps-dev): bump pycodestyle from 2.8.0 to 2.9.1
2022-08-09 12:32:19 +02:00
dependabot[bot]
f94314d8ec build(deps): bump smda from 1.7.4 to 1.8.4
Bumps [smda](https://github.com/danielplohmann/smda) from 1.7.4 to 1.8.4.
- [Release notes](https://github.com/danielplohmann/smda/releases)
- [Commits](https://github.com/danielplohmann/smda/commits)

---
updated-dependencies:
- dependency-name: smda
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-08 14:11:12 +00:00
dependabot[bot]
bb94ca3b18 build(deps-dev): bump pycodestyle from 2.8.0 to 2.9.1
Bumps [pycodestyle](https://github.com/PyCQA/pycodestyle) from 2.8.0 to 2.9.1.
- [Release notes](https://github.com/PyCQA/pycodestyle/releases)
- [Changelog](https://github.com/PyCQA/pycodestyle/blob/main/CHANGES.txt)
- [Commits](https://github.com/PyCQA/pycodestyle/compare/2.8.0...2.9.1)

---
updated-dependencies:
- dependency-name: pycodestyle
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-08 14:11:11 +00:00
Capa Bot
5823d421fd Sync capa-testfiles submodule 2022-08-01 20:50:09 +00:00
Capa Bot
045a64496e Sync capa-testfiles submodule 2022-08-01 20:36:11 +00:00
Capa Bot
b8905e3e48 Sync capa-testfiles submodule 2022-08-01 20:35:55 +00:00
Capa Bot
7c6f27c6d7 Sync capa-testfiles submodule 2022-08-01 20:35:14 +00:00
Capa Bot
995b144f0b Sync capa-testfiles submodule 2022-08-01 20:34:46 +00:00
Capa Bot
ba93803d3f Sync capa-testfiles submodule 2022-08-01 20:30:55 +00:00
dependabot[bot]
96b13907e2 build(deps-dev): bump pyinstaller from 5.2 to 5.3
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 5.2 to 5.3.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v5.2...v5.3)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 14:14:42 +00:00
Willi Ballenthin
2f7aa14f61 Merge pull request #1118 from mandiant/dependabot/pip/dncil-1.0.1
build(deps): bump dncil from 1.0.0 to 1.0.1
2022-07-25 10:57:12 -06:00
Willi Ballenthin
f93b94f073 Merge pull request #1119 from mandiant/dependabot/pip/smda-1.7.4
build(deps): bump smda from 1.7.2 to 1.7.4
2022-07-25 10:56:54 -06:00
Willi Ballenthin
30835b5ce4 Merge pull request #1120 from mandiant/dependabot/pip/mypy-0.971
build(deps-dev): bump mypy from 0.961 to 0.971
2022-07-25 10:56:19 -06:00
dependabot[bot]
98db89e45a build(deps-dev): bump mypy from 0.961 to 0.971
Bumps [mypy](https://github.com/python/mypy) from 0.961 to 0.971.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.961...v0.971)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-25 14:09:17 +00:00
dependabot[bot]
84c4b3ca8f build(deps): bump smda from 1.7.2 to 1.7.4
Bumps [smda](https://github.com/danielplohmann/smda) from 1.7.2 to 1.7.4.
- [Release notes](https://github.com/danielplohmann/smda/releases)
- [Commits](https://github.com/danielplohmann/smda/commits)

---
updated-dependencies:
- dependency-name: smda
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-25 14:09:11 +00:00
dependabot[bot]
cd32abc405 build(deps): bump dncil from 1.0.0 to 1.0.1
Bumps [dncil](https://github.com/mandiant/dncil) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/mandiant/dncil/releases)
- [Commits](https://github.com/mandiant/dncil/compare/v1.0.0...v1.0.1)

---
updated-dependencies:
- dependency-name: dncil
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-25 14:09:10 +00:00
dependabot[bot]
bae1b29505 build(deps-dev): bump types-colorama from 0.4.14 to 0.4.15 (#1113)
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.14 to 0.4.15.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-19 20:46:20 +02:00
dependabot[bot]
5061a0c717 build(deps-dev): bump types-requests from 2.28.0 to 2.28.1 (#1112)
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.0 to 2.28.1.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-19 20:45:53 +02:00
Capa Bot
404de45103 Sync capa rules submodule 2022-07-12 16:10:32 +00:00
Willi Ballenthin
39c8674da5 Merge pull request #1103 from mandiant/dependabot/pip/pyinstaller-5.2
build(deps-dev): bump pyinstaller from 5.1 to 5.2
2022-07-11 08:57:24 -06:00
Willi Ballenthin
954b90befb Merge pull request #1101 from mandiant/dependabot/pip/smda-1.7.2
build(deps): bump smda from 1.7.1 to 1.7.2
2022-07-11 08:56:18 -06:00
dependabot[bot]
62422ae4d9 build(deps-dev): bump pyinstaller from 5.1 to 5.2
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 5.1 to 5.2.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v5.1...v5.2)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 14:26:33 +00:00
dependabot[bot]
6594d9d911 build(deps): bump smda from 1.7.1 to 1.7.2
Bumps [smda](https://github.com/danielplohmann/smda) from 1.7.1 to 1.7.2.
- [Release notes](https://github.com/danielplohmann/smda/releases)
- [Commits](https://github.com/danielplohmann/smda/commits)

---
updated-dependencies:
- dependency-name: smda
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 14:26:26 +00:00
Anushka Virgaonkar
6e9676e0be fix #1095 (#1098) 2022-07-08 15:41:42 -06:00
Capa Bot
6764830f2d Sync capa-testfiles submodule 2022-07-08 18:59:42 +00:00
Mike Hunhoff
747eed4db7 render: display number feature as hex vverbose (#1097) 2022-07-08 10:37:41 -06:00
Capa Bot
28f32eebfc Sync capa rules submodule 2022-07-07 21:24:45 +00:00
Capa Bot
3dbd57ffe4 Sync capa rules submodule 2022-07-07 21:23:20 +00:00
Capa Bot
e63a9c801b Sync capa rules submodule 2022-07-07 19:40:55 +00:00
Capa Bot
0fbea75513 Sync capa rules submodule 2022-07-07 17:38:22 +00:00
Mike Hunhoff
4b3129e30a ida: bug fixes including #1090 for Address abstraction (#1091) 2022-07-07 09:54:20 -06:00
Anushka Virgaonkar
10c16e8a71 fix #1089: add feature format to global scope (#1093) 2022-07-07 08:15:34 +02:00
Capa Bot
21efdd2e0e Sync capa rules submodule 2022-07-06 19:36:29 +00:00
dependabot[bot]
ac1add3fcb build(deps-dev): bump black from 22.3.0 to 22.6.0 (#1085)
Bumps [black](https://github.com/psf/black) from 22.3.0 to 22.6.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.3.0...22.6.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2022-07-06 10:11:31 +02:00
Moritz
b4d2fecf4b fix: string extraction and rendering (#1083) 2022-07-05 13:17:24 -06:00
Capa Bot
ec81768fb5 Sync capa rules submodule 2022-07-05 15:37:24 +00:00
Capa Bot
0f60165135 Sync capa rules submodule 2022-07-05 07:53:28 +00:00
Capa Bot
7c54502dc8 Sync capa rules submodule 2022-07-05 07:17:51 +00:00
Moritz
38668b2c4a fix: use DnfileFeatureExtractor (#1088)
closes #1087
2022-07-05 07:53:47 +02:00
Moritz
d210645aee fix: api handling workaround (#1079)
* fix: api handling workaround

* fix: workaround .NET api handling
2022-07-01 17:37:56 +02:00
Capa Bot
444c30d720 Sync capa rules submodule 2022-07-01 14:50:27 +00:00
Willi Ballenthin
22bc26905f Merge pull request #1082 from mandiant/fix/addr-check
check address value
2022-07-01 08:49:17 -06:00
Moritz Raabe
9f4479582a check address value
closes #1081
2022-07-01 15:40:23 +02:00
Capa Bot
7bd49b56c4 Sync capa rules submodule 2022-06-30 15:17:33 +00:00
Capa Bot
9015761d4d Sync capa-testfiles submodule 2022-06-30 15:16:42 +00:00
Capa Bot
36eabc1c39 Sync capa rules submodule 2022-06-29 23:22:05 +00:00
Capa Bot
2f792427f9 Sync capa rules submodule 2022-06-29 17:55:13 +00:00
Capa Bot
cc06101cdc Sync capa rules submodule 2022-06-29 17:54:42 +00:00
Capa Bot
7387c56af9 Sync capa-testfiles submodule 2022-06-29 17:47:36 +00:00
Mike Hunhoff
998364d500 update documentation for .NET (#1074) 2022-06-29 08:22:48 -06:00
Willi Ballenthin
e7cf69a82e pep8 2022-06-28 15:58:02 -06:00
Willi Ballenthin
8dbb5a097c Merge branch 'master' of github.com:mandiant/capa 2022-06-28 15:54:19 -06:00
Willi Ballenthin
91818a116d scripts/capa_as_library: use new ResultDocument
closes #1071
2022-06-28 15:53:37 -06:00
Capa Bot
82e8f8f090 Sync capa rules submodule 2022-06-28 21:34:02 +00:00
Willi Ballenthin
2a0ada9848 Merge pull request #1072 from mandiant/revert-1014-fix/temp-accept-x32-x64-but-ignore
Revert "fix: temporarily accept x32/x64 flavors but ignore"
2022-06-28 14:28:08 -06:00
Willi Ballenthin
b87b03300a Revert "fix: temporarily accept x32/x64 flavors but ignore (#1014)"
This reverts commit daf483309e.
2022-06-28 14:27:48 -06:00
Capa Bot
ecd88680dd Sync capa rules submodule 2022-06-28 20:26:53 +00:00
Capa Bot
45c39cfd7a Sync capa rules submodule 2022-06-28 20:11:57 +00:00
Capa Bot
46ad23fb30 Sync capa rules submodule 2022-06-28 20:04:59 +00:00
Capa Bot
0e6a050921 Sync capa rules submodule 2022-06-28 20:04:14 +00:00
Moritz
f72f8b054a ci: use macos-11 (#1066)
* ci: use macos-11

* ci: use macos-10.15 for build
2022-06-28 21:47:06 +02:00
Willi Ballenthin
1d61b24eb0 Merge pull request #1055 from mandiant/dependabot/pip/types-requests-2.28.0
build(deps-dev): bump types-requests from 2.27.30 to 2.28.0
2022-06-28 11:35:09 -06:00
Willi Ballenthin
5a73a8d7bb Merge pull request #1069 from mandiant/fix-1053
render: verbose: render metadata tokens correctly
2022-06-28 11:30:48 -06:00
Willi Ballenthin
b2507d14c0 Merge pull request #1070 from mandiant/williballenthin-patch-1
changelog: document upcoming deprecation of SMDA backend
2022-06-28 11:30:10 -06:00
Willi Ballenthin
b6f932ea15 changelog: document upcoming deprecation of SMDA backend
closes #1061
2022-06-28 11:24:31 -06:00
Willi Ballenthin
bb1afb3356 render: verbose: render metadata tokens correctly
closes #1053
2022-06-28 11:18:24 -06:00
Capa Bot
d35ac32f0a Sync capa rules submodule 2022-06-28 17:13:42 +00:00
Willi Ballenthin
cb6781a143 verbose: remove extraneous import 2022-06-28 11:11:00 -06:00
Willi Ballenthin
e7fa1ae52c Merge pull request #1068 from mandiant/feat-lint-dotnet-filename
linter: expect file path "dotnet" for ".NET" rules
2022-06-28 11:05:37 -06:00
Willi Ballenthin
8b7ddc5679 linter: expect file path "dotnet" for ".NET" rules
ref: https://github.com/mandiant/capa-rules/pull/568#discussion_r908718249
2022-06-28 10:48:03 -06:00
Willi Ballenthin
3323d85067 Merge pull request #1067 from mandiant/fix-966
main: suppress low level ELF parsing log messages
2022-06-28 10:46:32 -06:00
Willi Ballenthin
9019e6b0f5 main: suppress low level ELF parsing log messages
closes #966
2022-06-28 10:45:38 -06:00
Capa Bot
c6c2fc9f2a Sync capa rules submodule 2022-06-28 16:44:02 +00:00
Willi Ballenthin
6ea15901d6 Merge pull request #1064 from mandiant/mr-tz-patch-1
Update README.md
2022-06-28 10:42:44 -06:00
Willi Ballenthin
400e28c3f7 document rule branches (#1006)
* doc: add rules documentation

* version: add accessor for capa major version and git checkout command

* doc: rules: document version output

* doc: rules: show example error due to mismatched rule version

* doc: rules: update links

* ci: tag major rule version test

* ci: tag major rule version

* doc: update changelog

* ci: force to replace tag if exists

* ci: simplify tagging step

* Update doc/rules.md

* feat: disable tag, show error branch cmd

* doc: update major version rules branch

* Apply suggestions from code review

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

* Update capa/main.py

* black

Co-authored-by: Moritz Raabe <moritz.raabe@mandiant.com>
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2022-06-28 18:38:51 +02:00
Moritz
f2281b8e6e Update README.md 2022-06-28 18:33:42 +02:00
Willi Ballenthin
ad88e51228 Merge pull request #1060 from mandiant/feat/frz-extractor-info
Feat/frz extractor info
2022-06-28 10:32:37 -06:00
Capa Bot
2b17b22d33 Sync capa rules submodule 2022-06-28 16:30:17 +00:00
Willi Ballenthin
da6f6dd94f Merge pull request #1063 from mandiant/fix-blog-links
readme: fix blog links
2022-06-28 10:30:08 -06:00
Willi Ballenthin
09d444222a readme: fix blog links
closes #800
2022-06-28 10:27:31 -06:00
Capa Bot
a5c9993b61 Sync capa rules submodule 2022-06-28 14:06:49 +00:00
Moritz
f03eb87892 Merge pull request #1059 from mandiant/fix/linter-refs-authors
feat: lint check value types
2022-06-28 15:57:39 +02:00
Moritz Raabe
a7c4761fef isort, black 2022-06-28 15:53:10 +02:00
Moritz Raabe
e2156c3854 refactor: parametrize test 2022-06-28 15:49:21 +02:00
Moritz Raabe
bf53958887 fix!: global feat frz address 2022-06-28 15:47:12 +02:00
Moritz Raabe
e4d532e212 feat!: add extractor info to frz format 2022-06-28 15:43:59 +02:00
Moritz Raabe
9bf582a89a feat: lint check value types
closes #1027
2022-06-28 12:53:31 +02:00
dependabot[bot]
470995a541 build(deps-dev): bump types-requests from 2.27.30 to 2.28.0
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.30 to 2.28.0.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 14:10:51 +00:00
Capa Bot
79ce903817 Sync capa rules submodule 2022-06-23 13:27:54 +00:00
Willi Ballenthin
6fa8f9e401 Merge pull request #1052 from mandiant/dependabot/pip/colorama-0.4.5
build(deps): bump colorama from 0.4.4 to 0.4.5
2022-06-21 09:45:21 -06:00
Willi Ballenthin
fb99ef56e3 Merge pull request #986 from mandiant/feature-981
add Address abstraction
2022-06-21 09:44:57 -06:00
Willi Ballenthin
be2dffe863 bulk-process: use new ResultDocument json 2022-06-20 14:43:30 -06:00
Willi Ballenthin
e3804a0596 main: add types for collect_metadata 2022-06-20 14:43:18 -06:00
Willi Ballenthin
9ebea05933 show-capabilities-by-function: use new ResultDocument 2022-06-20 14:32:10 -06:00
Willi Ballenthin
a453258a51 tests: fix render test for MBC 2022-06-20 14:25:18 -06:00
Willi Ballenthin
246ef58e7b tests: fix render test for ATT&CK metadata 2022-06-20 14:24:01 -06:00
dependabot[bot]
d55d1facd5 build(deps): bump colorama from 0.4.4 to 0.4.5
Bumps [colorama](https://github.com/tartley/colorama) from 0.4.4 to 0.4.5.
- [Release notes](https://github.com/tartley/colorama/releases)
- [Changelog](https://github.com/tartley/colorama/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/tartley/colorama/compare/0.4.4...0.4.5)

---
updated-dependencies:
- dependency-name: colorama
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-20 14:20:36 +00:00
William Ballenthin
a5979d3b4d Merge branch 'feature-981' of github.com:fireeye/capa into feature-981 2022-06-14 17:43:24 -06:00
William Ballenthin
af9049da6e dnfile: return NO_ADDRESS for base_address 2022-06-14 17:43:04 -06:00
William Ballenthin
6b5e125592 extractors: mypy 2022-06-14 17:42:04 -06:00
William Ballenthin
ee5c86913d extractor: clarify base address handling 2022-06-14 17:40:04 -06:00
Willi Ballenthin
0ff3bf1e5e Update .github/workflows/tests.yml 2022-06-14 17:07:25 -06:00
Willi Ballenthin
f5b79c0285 Update .github/workflows/tests.yml 2022-06-14 17:06:48 -06:00
William Ballenthin
c417b5dd79 merge master 2022-06-14 17:05:46 -06:00
William Ballenthin
bb74c73f6f sync rules 2022-06-14 17:02:34 -06:00
Willi Ballenthin
df101e5a60 Update capa/features/extractors/dnfile/extractor.py
Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>
2022-06-14 17:01:20 -06:00
William Ballenthin
aff6191b11 ida: meta: provide [] as argv 2022-06-14 16:59:58 -06:00
William Ballenthin
269f056e52 ida: use new ResultDocument structures 2022-06-14 16:58:32 -06:00
William Ballenthin
9c77488937 ida: meta: extract os/format/platform 2022-06-14 16:57:19 -06:00
Moritz
2ceed78924 Merge pull request #1050 from mandiant/dependabot/pip/mypy-0.961
build(deps-dev): bump mypy from 0.960 to 0.961
2022-06-13 19:24:37 +02:00
Moritz
df99b1d394 Merge pull request #1049 from mandiant/dependabot/pip/requests-2.28.0
build(deps-dev): bump requests from 2.27.1 to 2.28.0
2022-06-13 19:24:29 +02:00
dependabot[bot]
57633ceeb2 build(deps-dev): bump mypy from 0.960 to 0.961
Bumps [mypy](https://github.com/python/mypy) from 0.960 to 0.961.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.960...v0.961)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 14:16:18 +00:00
dependabot[bot]
7aa041c4d1 build(deps-dev): bump requests from 2.27.1 to 2.28.0
Bumps [requests](https://github.com/psf/requests) from 2.27.1 to 2.28.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.27.1...v2.28.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 14:16:11 +00:00
Willi Ballenthin
8031be75ab render: fix computation of subrule matches 2022-06-10 15:06:22 -06:00
Willi Ballenthin
3103307601 tests: fix reference error 2022-06-10 14:58:26 -06:00
Willi Ballenthin
6568189839 freeze: fix sorting of addresses 2022-06-10 14:58:17 -06:00
Capa Bot
c653dd7e72 Sync capa-testfiles submodule 2022-06-10 20:48:49 +00:00
Willi Ballenthin
1c771da848 pep8 2022-06-10 14:47:23 -06:00
Willi Ballenthin
5b5ac16830 render: fix rendering of .NET tokens 2022-06-10 14:47:06 -06:00
Willi Ballenthin
67221e5907 freeze: fix (de)serialization of tokens 2022-06-10 14:46:56 -06:00
Willi Ballenthin
6a5271c16f remove old file 2022-06-10 14:38:14 -06:00
William Ballenthin
c3418fddb5 tests: json: fix address representation 2022-06-08 13:29:04 -06:00
William Ballenthin
faf414e3d8 tests: add more dotnet tests 2022-06-08 13:28:53 -06:00
William Ballenthin
c6144a1dfa freeze: address: fix .NET address sorting 2022-06-08 13:07:10 -06:00
William Ballenthin
ad153499a3 address: implement __eq__ 2022-06-08 12:46:50 -06:00
William Ballenthin
2767660722 features: substring: correctly record no captures 2022-06-08 11:09:53 -06:00
Willi Ballenthin
9433d41588 Update capa/features/address.py
Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>
2022-06-08 10:10:20 -06:00
Willi Ballenthin
96b522cf6c Update capa/features/address.py
Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>
2022-06-08 10:10:12 -06:00
Willi Ballenthin
f35a82562b Update capa/features/extractors/dnfile/insn.py
Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>
2022-06-08 10:00:21 -06:00
Willi Ballenthin
bfda997fdf freeze: support Class and Namespace features, too 2022-06-06 15:55:12 -06:00
Willi Ballenthin
9c09923b86 main: fix .NET format detection 2022-06-06 15:46:40 -06:00
Willi Ballenthin
3ef126fbd7 show-features: fix rendering addresses 2022-06-06 15:27:06 -06:00
Willi Ballenthin
9fdaa91fa9 render: vverbose: fixup rendering of imports 2022-06-06 15:22:06 -06:00
Willi Ballenthin
0987141970 tests: add tests demonstrating rending of .NET samples 2022-06-06 15:13:20 -06:00
Willi Ballenthin
c73db051c1 fixtures: add path to extractors 2022-06-06 15:13:11 -06:00
Willi Ballenthin
9a8d28d107 viv: remove old handle implementation 2022-06-06 15:05:24 -06:00
Willi Ballenthin
0b11a35358 Merge pull request #1045 from mandiant/dependabot/pip/types-requests-2.27.30
build(deps-dev): bump types-requests from 2.27.29 to 2.27.30
2022-06-06 15:00:48 -06:00
dependabot[bot]
524ab86d24 build(deps-dev): bump types-requests from 2.27.29 to 2.27.30
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.29 to 2.27.30.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 21:00:10 +00:00
Willi Ballenthin
0060daf2e8 Merge pull request #1046 from mandiant/dependabot/pip/types-psutil-5.8.23
build(deps-dev): bump types-psutil from 5.8.22 to 5.8.23
2022-06-06 14:59:18 -06:00
Willi Ballenthin
f5eb52f7c9 Merge pull request #1048 from mandiant/dependabot/pip/types-pyyaml-6.0.8
build(deps-dev): bump types-pyyaml from 6.0.7 to 6.0.8
2022-06-06 14:59:01 -06:00
Willi Ballenthin
59944d6aa6 Merge pull request #1039 from mandiant/dependabot/pip/pefile-2022.5.30
build(deps): bump pefile from 2021.9.3 to 2022.5.30
2022-06-06 14:58:52 -06:00
Willi Ballenthin
a6a48dc7a3 Merge pull request #1047 from mandiant/dependabot/pip/viv-utils-flirt--0.7.5
build(deps): bump viv-utils[flirt] from 0.7.4 to 0.7.5
2022-06-06 14:58:43 -06:00
Willi Ballenthin
1b951aa2d5 *: remove unused imports 2022-06-06 14:33:34 -06:00
Willi Ballenthin
a66c6c9d23 setup: fix pydantic dep version 2022-06-06 14:29:22 -06:00
Willi Ballenthin
dddcec4be3 setup: fix dep spec 2022-06-06 14:27:34 -06:00
Willi Ballenthin
1a290a38c4 Merge branch 'master' into feature-981 2022-06-06 14:07:51 -06:00
Willi Ballenthin
dcdc70de49 Merge branch 'feature-981' of github.com:mandiant/capa into feature-981 2022-06-06 13:49:28 -06:00
Willi Ballenthin
f8b10a2c0a render: verbose: update to use new result document 2022-06-06 13:48:41 -06:00
Willi Ballenthin
5960f51f13 result document: fix type of statement node 2022-06-06 13:47:39 -06:00
Willi Ballenthin
59e0518e6d pep8/mypy 2022-06-06 13:47:17 -06:00
Willi Ballenthin
afc2953538 frz: address: make sortable 2022-06-06 13:45:13 -06:00
Willi Ballenthin
f58966acf8 address: implement repr, not str 2022-06-06 13:44:59 -06:00
Willi Ballenthin
cb44704d38 features: bb: add description to BasicBlock feature 2022-06-06 13:44:40 -06:00
Willi Ballenthin
ab4177fae1 render: default: fix rendering of mbc/att&ck 2022-06-06 13:44:08 -06:00
Willi Ballenthin
867662ba5a rules: remove unused rule-category meta 2022-06-06 13:43:44 -06:00
Capa Bot
6cb4493b8e Sync capa rules submodule 2022-06-06 19:18:31 +00:00
dependabot[bot]
0444ab0bc5 build(deps-dev): bump types-pyyaml from 6.0.7 to 6.0.8
Bumps [types-pyyaml](https://github.com/python/typeshed) from 6.0.7 to 6.0.8.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 14:11:09 +00:00
dependabot[bot]
51a2da7e05 build(deps): bump viv-utils[flirt] from 0.7.4 to 0.7.5
Bumps [viv-utils[flirt]](https://github.com/williballenthin/viv-utils) from 0.7.4 to 0.7.5.
- [Release notes](https://github.com/williballenthin/viv-utils/releases)
- [Commits](https://github.com/williballenthin/viv-utils/compare/v0.7.4...v0.7.5)

---
updated-dependencies:
- dependency-name: viv-utils[flirt]
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 14:11:08 +00:00
dependabot[bot]
d625e99dd0 build(deps-dev): bump types-psutil from 5.8.22 to 5.8.23
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.22 to 5.8.23.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 14:11:03 +00:00
Capa Bot
43dca13f26 Sync capa rules submodule 2022-06-03 17:16:28 +00:00
Capa Bot
bc8c4a0323 Sync capa rules submodule 2022-06-01 12:13:22 +00:00
Moritz
d8e68255a0 Merge pull request #1044 from mandiant/fix/rules-meta-authors
fix!: authors instead of author
2022-06-01 14:12:31 +02:00
Capa Bot
781ec74310 Sync capa-testfiles submodule 2022-06-01 12:12:01 +00:00
Moritz Raabe
1df60186f0 fix!: authors instead of author 2022-05-31 23:05:13 +02:00
Moritz
b8e297c5ba Merge pull request #1043 from mandiant/mr-tz-patch-1
Update build.yml
2022-05-31 22:40:45 +02:00
Zander Work
486ffed4bd ignore .git/ when loading capa rules (#1038)
* ignore .git/ when loading capa rules

* moved check outside of for loop
2022-05-31 22:35:28 +02:00
Moritz
cb703aea18 Update build.yml 2022-05-31 22:33:53 +02:00
Willi Ballenthin
5084cb0887 Merge branch 'feature-981' of github.com:mandiant/capa into feature-981 2022-05-31 07:45:38 -06:00
Willi Ballenthin
5d6c12d900 sync rules 2022-05-31 07:45:13 -06:00
Capa Bot
2f47fddda9 Sync capa rules submodule 2022-05-31 13:42:34 +00:00
Willi Ballenthin
42e2c53e5e wip: pydantic result document 2022-05-31 07:40:50 -06:00
Willi Ballenthin
8080752815 freeze: pass descriptions around 2022-05-31 07:40:30 -06:00
Willi Ballenthin
2dec484676 typing fixes 2022-05-31 07:40:20 -06:00
Moritz
3d0a59cf74 Update pyinstaller.spec (#1042)
* Update pyinstaller.spec
2022-05-31 13:29:04 +02:00
Moritz
5169568c3b Merge pull request #1034 from mandiant/dependabot/pip/pyinstaller-5.1
build(deps-dev): bump pyinstaller from 5.0.1 to 5.1
2022-05-31 12:33:38 +02:00
dependabot[bot]
44a5dc0cd0 build(deps-dev): bump pyinstaller from 5.0.1 to 5.1
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 5.0.1 to 5.1.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v5.0.1...v5.1)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-31 09:18:38 +00:00
Moritz
1f38004114 Merge pull request #1040 from mandiant/dependabot/pip/mypy-0.960
build(deps-dev): bump mypy from 0.950 to 0.960
2022-05-31 11:18:04 +02:00
Moritz
8e7143556b Merge pull request #1041 from mandiant/dependabot/pip/types-requests-2.27.29
build(deps-dev): bump types-requests from 2.27.27 to 2.27.29
2022-05-31 11:17:52 +02:00
dependabot[bot]
2f519cba30 build(deps-dev): bump types-requests from 2.27.27 to 2.27.29
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.27 to 2.27.29.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 14:14:17 +00:00
dependabot[bot]
02444d801e build(deps-dev): bump mypy from 0.950 to 0.960
Bumps [mypy](https://github.com/python/mypy) from 0.950 to 0.960.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.950...v0.960)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 14:14:14 +00:00
dependabot[bot]
85d4991cb3 build(deps): bump pefile from 2021.9.3 to 2022.5.30
Bumps [pefile](https://github.com/erocarrera/pefile) from 2021.9.3 to 2022.5.30.
- [Release notes](https://github.com/erocarrera/pefile/releases)
- [Commits](https://github.com/erocarrera/pefile/commits)

---
updated-dependencies:
- dependency-name: pefile
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 14:14:11 +00:00
Willi Ballenthin
4ae4bab254 lint: use meta.authors 2022-05-26 12:02:47 -06:00
Mike Hunhoff
3514d5c05c dotnet: support file/function scope class and namespace features (#1030) 2022-05-26 11:19:31 -06:00
Willi Ballenthin
9236a36ef4 rule: factor out is subscope check 2022-05-26 10:24:31 -06:00
Willi Ballenthin
b2318ce957 features: remove freeze_(de)serialize with preference to freeze module 2022-05-25 17:19:56 -06:00
Willi Ballenthin
3879e33cce freeze: model each features separately 2022-05-25 17:12:02 -06:00
Willi Ballenthin
eb6de90059 changelog 2022-05-25 15:30:46 -06:00
Willi Ballenthin
6b633efdba freeze: fix schema to support overlapping functions 2022-05-25 15:28:02 -06:00
Willi Ballenthin
02cef8297c pep8 2022-05-25 15:27:56 -06:00
Willi Ballenthin
adb425aeb3 freeze: use pydantic for (de)serialization
also, move null extractor to its own namespace
2022-05-25 15:09:31 -06:00
Willi Ballenthin
b1fa5be7b1 show-features: render features in a tree to better group scopes 2022-05-25 15:08:44 -06:00
Willi Ballenthin
d7cfa4ee96 features: make features implement __lt__ 2022-05-25 15:08:26 -06:00
Willi Ballenthin
46a79f43bb Merge pull request #1037 from mandiant/gh-codespaces
add Github Codespaces config
2022-05-25 11:38:15 -06:00
Willi Ballenthin
5a71caf09c add Github Codespaces config 2022-05-25 14:44:10 +00:00
Willi Ballenthin
a4003d7d91 tests: fix scripts using json document 2022-05-24 14:50:17 -06:00
Willi Ballenthin
b35fe6cdb2 json, render: work with and serialize addresses 2022-05-24 13:52:56 -06:00
Willi Ballenthin
d728869690 freeze: mypy and pep8 2022-05-24 13:52:40 -06:00
Willi Ballenthin
6b6dd70110 freeze: use address abstraction 2022-05-24 12:30:06 -06:00
Willi Ballenthin
fc9681f6d5 helpers: fix import loop 2022-05-24 12:29:56 -06:00
Willi Ballenthin
e4caa1d729 base extractor: use handles 2022-05-24 12:29:38 -06:00
Willi Ballenthin
4a577fabfc Merge pull request #1031 from mandiant/fix/ida-plugin
fix: rule generator handles
2022-05-23 11:29:48 -06:00
Willi Ballenthin
314ad4ea4d Merge pull request #1028 from mandiant/fix-988
elf: better detect Linux OS
2022-05-23 11:29:13 -06:00
Willi Ballenthin
2b446c75dd Merge pull request #1032 from mandiant/dependabot/pip/types-requests-2.27.27
build(deps-dev): bump types-requests from 2.27.25 to 2.27.27
2022-05-23 11:28:51 -06:00
Willi Ballenthin
ecf22c2c50 Merge pull request #1033 from mandiant/dependabot/pip/psutil-5.9.1
build(deps-dev): bump psutil from 5.9.0 to 5.9.1
2022-05-23 11:28:43 -06:00
dependabot[bot]
6f234b57fc build(deps-dev): bump psutil from 5.9.0 to 5.9.1
Bumps [psutil](https://github.com/giampaolo/psutil) from 5.9.0 to 5.9.1.
- [Release notes](https://github.com/giampaolo/psutil/releases)
- [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst)
- [Commits](https://github.com/giampaolo/psutil/compare/release-5.9.0...release-5.9.1)

---
updated-dependencies:
- dependency-name: psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 14:10:27 +00:00
dependabot[bot]
ddb6c810eb build(deps-dev): bump types-requests from 2.27.25 to 2.27.27
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.25 to 2.27.27.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 14:10:21 +00:00
Capa Bot
8f2c9cbd11 Sync capa rules submodule 2022-05-20 14:36:37 +00:00
Moritz Raabe
a4f0c1c04c fix: rule generator handles 2022-05-19 20:43:02 +02:00
Willi Ballenthin
7642db332a Merge pull request #1029 from mandiant/feat/981-add-ida-handles
feat: add IDA handles and type annotations
2022-05-17 09:33:46 -06:00
Moritz Raabe
8e1f710312 fix: add __str__ 2022-05-12 18:49:53 +02:00
Moritz Raabe
83cae29dbe ci: temporarily test on PR 2022-05-12 18:40:45 +02:00
Moritz Raabe
b2853cc56b feat: update dnfile tests and extractor 2022-05-12 18:37:02 +02:00
Moritz Raabe
d8c9941f6b fix: filter address 2022-05-12 16:39:36 +02:00
Moritz Raabe
716a73dfb4 feat: add handles and type annotations 2022-05-12 15:42:25 +02:00
Capa Bot
cded1d3125 Sync capa-testfiles submodule 2022-05-12 06:35:04 +00:00
Willi Ballenthin
7b05fc4180 pep8 + mypy 2022-05-11 13:25:25 -06:00
Willi Ballenthin
78e9280a93 Merge branch 'master' into feature-981 2022-05-11 13:20:48 -06:00
Willi Ballenthin
ca2adb85b0 Merge pull request #1026 from mandiant/dependabot/pip/types-colorama-0.4.14
build(deps-dev): bump types-colorama from 0.4.13 to 0.4.14
2022-05-11 13:12:39 -06:00
Willi Ballenthin
fca612e873 Merge pull request #1025 from mandiant/dependabot/pip/types-tabulate-0.8.9
build(deps-dev): bump types-tabulate from 0.8.8 to 0.8.9
2022-05-11 13:12:30 -06:00
Willi Ballenthin
07e35780d3 Merge branch 'master' into fix-988 2022-05-11 13:10:45 -06:00
Willi Ballenthin
521cbf9104 pep8 2022-05-11 13:10:08 -06:00
Willi Ballenthin
a6427364e0 tests: add test demonstrating elf OS detection 2022-05-11 13:09:12 -06:00
Willi Ballenthin
c30ce6e73a changelog 2022-05-11 12:54:30 -06:00
Willi Ballenthin
e4abe46d16 elf: better detect Linux OS
closes #988
2022-05-11 12:53:17 -06:00
Willi Ballenthin
71cf19b850 render: handle dn tokens 2022-05-11 12:51:42 -06:00
Willi Ballenthin
a734a045ae dnfile: address: use rva 2022-05-11 12:51:29 -06:00
Capa Bot
141da27715 Sync capa rules submodule 2022-05-11 16:34:46 +00:00
dependabot[bot]
7971b94001 build(deps-dev): bump types-colorama from 0.4.13 to 0.4.14
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.13 to 0.4.14.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 14:13:43 +00:00
dependabot[bot]
95b3c6a594 build(deps-dev): bump types-tabulate from 0.8.8 to 0.8.9
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.8 to 0.8.9.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 14:13:40 +00:00
Mike Hunhoff
0d849142ba dotnet: emit mixed mode characteristic (#1024) 2022-05-06 14:32:06 -06:00
Moritz
f96c7379e0 Merge pull request #1021 from mandiant/ci/fix-build-workflow
ci: build on PR
2022-05-06 22:07:53 +02:00
Mike Hunhoff
6fb9dd961a dotnet: emit unmanaged call characteristic (#1023) 2022-05-06 13:05:48 -06:00
Mike Hunhoff
a9c9b3cea8 dotnet: extract file function names (#1015) 2022-05-06 08:34:50 -06:00
Moritz
ff2810654e Merge pull request #1018 from mandiant/dependabot/pip/vivisect-1.0.8
build(deps): bump vivisect from 1.0.7 to 1.0.8
2022-05-06 16:30:38 +02:00
Moritz Raabe
80e4161b40 ci: build on PR 2022-05-06 16:29:54 +02:00
Moritz
0473ce3259 Merge pull request #1017 from mandiant/dependabot/pip/mypy-0.950
build(deps-dev): bump mypy from 0.942 to 0.950
2022-05-06 15:50:15 +02:00
Moritz
0a211c1461 Merge pull request #1019 from mandiant/dependabot/pip/types-termcolor-1.1.4
build(deps-dev): bump types-termcolor from 1.1.3 to 1.1.4
2022-05-06 15:50:00 +02:00
Moritz Raabe
5573794a1f dep: bump viv-utils 2022-05-06 15:49:04 +02:00
dependabot[bot]
d0a1313f33 build(deps-dev): bump types-termcolor from 1.1.3 to 1.1.4
Bumps [types-termcolor](https://github.com/python/typeshed) from 1.1.3 to 1.1.4.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-termcolor
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-05 20:21:15 +00:00
dependabot[bot]
aca4f27ee8 build(deps-dev): bump mypy from 0.942 to 0.950
Bumps [mypy](https://github.com/python/mypy) from 0.942 to 0.950.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.942...v0.950)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-05 20:20:18 +00:00
dependabot[bot]
bcd00004b8 build(deps-dev): bump types-tabulate from 0.8.7 to 0.8.8 (#1009) 2022-05-05 14:20:16 -06:00
dependabot[bot]
eefc0a9632 build(deps-dev): bump pyinstaller from 5.0 to 5.0.1 (#1008) 2022-05-05 14:19:56 -06:00
dependabot[bot]
dcf43b6fee build(deps): bump vivisect from 1.0.7 to 1.0.8
Bumps [vivisect](https://github.com/vivisect/vivisect) from 1.0.7 to 1.0.8.
- [Release notes](https://github.com/vivisect/vivisect/releases)
- [Changelog](https://github.com/vivisect/vivisect/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/vivisect/vivisect/compare/v1.0.7...v1.0.8)

---
updated-dependencies:
- dependency-name: vivisect
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-05 20:19:53 +00:00
dependabot[bot]
6d218aaf0d build(deps-dev): bump types-requests from 2.27.20 to 2.27.25 (#1007) 2022-05-05 14:19:35 -06:00
dependabot[bot]
20d80c1a2e build(deps-dev): bump types-colorama from 0.4.12 to 0.4.13 (#1010) 2022-05-05 14:19:21 -06:00
Mike Hunhoff
24c4215820 dotnet: add file string parsing (#1012) 2022-05-05 13:39:29 -06:00
dependabot[bot]
0066b3f33a build(deps): bump dnfile from 0.10.0 to 0.11.0 (#1004) 2022-05-05 13:28:48 -06:00
Moritz
daf483309e fix: temporarily accept x32/x64 flavors but ignore (#1014) 2022-05-05 20:19:35 +02:00
Capa Bot
49b1296d6e Sync capa rules submodule 2022-04-27 17:18:08 +00:00
Moritz
9f12f069ee ci: fix build (#980)
* ci: fix build

* fix: newest PyInstaller version

* fix: logo path

* fix: logo path 2

* fix: logo path 3

* fix: icon another way

* fix: remove icon for now

* ci: only build after tests succeed

* ci: add workflow_run check
2022-04-27 15:09:58 +02:00
Capa Bot
10852a5d96 Sync capa rules submodule 2022-04-27 11:36:08 +00:00
Moritz
3347245c2e Merge pull request #1003 from mandiant/dependabot/pip/viv-utils-flirt--0.7.1
build(deps): bump viv-utils[flirt] from 0.6.11 to 0.7.1
2022-04-26 21:09:13 +02:00
Moritz
3e8e88c363 Merge pull request #1002 from mandiant/dependabot/pip/types-requests-2.27.20
build(deps-dev): bump types-requests from 2.27.19 to 2.27.20
2022-04-26 21:08:54 +02:00
Moritz
e4dfa45057 Merge pull request #1001 from mandiant/dependabot/pip/types-pyyaml-6.0.7
build(deps-dev): bump types-pyyaml from 6.0.6 to 6.0.7
2022-04-26 21:08:44 +02:00
Moritz
b58e90e8dd Merge pull request #1000 from mandiant/dependabot/pip/pytest-7.1.2
build(deps-dev): bump pytest from 7.1.1 to 7.1.2
2022-04-26 21:08:31 +02:00
dependabot[bot]
0e18cea11a build(deps): bump viv-utils[flirt] from 0.6.11 to 0.7.1
Bumps [viv-utils[flirt]](https://github.com/williballenthin/viv-utils) from 0.6.11 to 0.7.1.
- [Release notes](https://github.com/williballenthin/viv-utils/releases)
- [Commits](https://github.com/williballenthin/viv-utils/compare/v0.6.11...v0.7.1)

---
updated-dependencies:
- dependency-name: viv-utils[flirt]
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-25 14:13:34 +00:00
dependabot[bot]
e950932e43 build(deps-dev): bump types-requests from 2.27.19 to 2.27.20
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.19 to 2.27.20.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-25 14:13:31 +00:00
dependabot[bot]
45738773ca build(deps-dev): bump types-pyyaml from 6.0.6 to 6.0.7
Bumps [types-pyyaml](https://github.com/python/typeshed) from 6.0.6 to 6.0.7.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-25 14:13:28 +00:00
dependabot[bot]
054bcc9cb8 build(deps-dev): bump pytest from 7.1.1 to 7.1.2
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.1 to 7.1.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.1.1...7.1.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-25 14:13:26 +00:00
Moritz
4d49b749c5 Merge pull request #998 from mandiant/dependabot/pip/types-tabulate-0.8.7
build(deps-dev): bump types-tabulate from 0.8.6 to 0.8.7
2022-04-20 17:53:08 +02:00
Moritz
4d86774266 Merge pull request #997 from mandiant/dependabot/pip/types-colorama-0.4.12
build(deps-dev): bump types-colorama from 0.4.10 to 0.4.12
2022-04-20 17:52:57 +02:00
Moritz
20171fe4f2 Merge pull request #995 from mandiant/dependabot/pip/types-psutil-5.8.22
build(deps-dev): bump types-psutil from 5.8.20 to 5.8.22
2022-04-20 17:52:40 +02:00
dependabot[bot]
308a47a784 build(deps-dev): bump types-tabulate from 0.8.6 to 0.8.7
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.6 to 0.8.7.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-20 15:48:18 +00:00
dependabot[bot]
2226bf0faa build(deps-dev): bump types-psutil from 5.8.20 to 5.8.22
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.20 to 5.8.22.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-20 15:48:17 +00:00
dependabot[bot]
65cf8509f9 build(deps-dev): bump types-colorama from 0.4.10 to 0.4.12
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.10 to 0.4.12.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-20 15:48:15 +00:00
Moritz
523ec7f453 Merge pull request #996 from mandiant/dependabot/pip/types-pyyaml-6.0.6
build(deps-dev): bump types-pyyaml from 6.0.5 to 6.0.6
2022-04-20 17:47:32 +02:00
Moritz
8a1bc39eb2 Merge pull request #994 from mandiant/dependabot/pip/types-requests-2.27.19
build(deps-dev): bump types-requests from 2.27.16 to 2.27.19
2022-04-20 17:45:36 +02:00
dependabot[bot]
fd1785fe65 build(deps-dev): bump types-pyyaml from 6.0.5 to 6.0.6
Bumps [types-pyyaml](https://github.com/python/typeshed) from 6.0.5 to 6.0.6.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-18 14:12:43 +00:00
dependabot[bot]
45c22a24a6 build(deps-dev): bump types-requests from 2.27.16 to 2.27.19
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.16 to 2.27.19.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-18 14:12:38 +00:00
Willi Ballenthin
c236293185 features: insn: number: allow floats, too 2022-04-08 18:41:19 -06:00
Willi Ballenthin
bfb6d4d142 dn: fix access to ctx 2022-04-08 18:41:09 -06:00
Willi Ballenthin
723efe1755 address: better implement .NET token 2022-04-08 18:40:58 -06:00
Willi Ballenthin
e029547035 show-features: learn to use Addresses 2022-04-08 18:33:49 -06:00
Willi Ballenthin
d9ede95cf7 dnfile: use Address 2022-04-08 18:33:39 -06:00
Willi Ballenthin
70c3487bc7 address: better implement .NET token 2022-04-08 18:33:23 -06:00
Willi Ballenthin
808b7fb4dc dnfile: fix types 2022-04-08 18:33:12 -06:00
Willi Ballenthin
ed1009096d Merge branch 'master' of github.com:mandiant/capa into feature-981 2022-04-08 16:01:59 -06:00
Mike Hunhoff
580a2d7e45 dotnet: basic detection and feature extraction (#987) 2022-04-08 14:55:00 -06:00
Willi Ballenthin
87d3d6c577 smda: use Addresses 2022-04-08 13:15:04 -06:00
Willi Ballenthin
ae87fa1785 elf: use addresses 2022-04-08 12:49:48 -06:00
Willi Ballenthin
2b00bc0fdb pep8 2022-04-08 12:46:43 -06:00
Willi Ballenthin
43b8ad80c7 pefile: extract Addresses 2022-04-08 12:45:46 -06:00
Willi Ballenthin
65b462f62c render: format various address types differently 2022-04-08 12:39:10 -06:00
Willi Ballenthin
7e7740cf77 viv: insn: use handles for code merged from master 2022-04-08 12:38:46 -06:00
Willi Ballenthin
a3d1b1403c address: fix min value for unsigned addresses 2022-04-08 12:38:21 -06:00
Willi Ballenthin
31977e6523 changelog 2022-04-08 12:19:50 -06:00
Willi Ballenthin
9164713dd9 Merge branch 'dotnet-main' of github.com:mandiant/capa into feature-981 2022-04-08 12:17:16 -06:00
Willi Ballenthin
bfb01e3729 extractor: viv: use handles throughout 2022-04-08 11:54:27 -06:00
Willi Ballenthin
fc1709ba6c extractor: add types throughout 2022-04-08 11:53:42 -06:00
Willi Ballenthin
1b79aae836 extractor: introduce standardized handles for function, bb, insn 2022-04-08 11:46:07 -06:00
Willi Ballenthin
6355fb3f3e add Address abstraction to handle various ways of identifing things in files 2022-04-08 11:44:24 -06:00
Moritz
c8a772d19a test: update dotnet dirs and sync master (#984) 2022-04-08 09:34:22 -06:00
Capa Bot
5bc44aef0f Sync capa-testfiles submodule 2022-04-08 10:34:02 +00:00
Willi Ballenthin
b455b67da3 Merge pull request #977 from mandiant/feature-320
extract extra offset/number features
2022-04-07 14:20:10 -06:00
Willi Ballenthin
351d70aafe smda: implement additional offset and number features 2022-04-07 12:56:24 -06:00
Willi Ballenthin
8a2276f398 smda: implement operand number/offset features
cause its not too hard
2022-04-07 12:48:25 -06:00
Moritz
65552575f8 Update dotnet-main (#979)
* Sync capa rules submodule

* Sync capa-testfiles submodule

* Sync capa rules submodule

* changelog

* *: remove /x32 and /x64 flavors from number and offset features

* *: remove more references to /x32 and /x64

* linter: accept instruction scope

* rules: fix max operand index (4)

* API: better support A/W functions

* vverbose: show lib rule matches

* main: accept multiple paths to rules

* main: fix removal of default rules path

* lint: fix rules path

* changelog

* capa_as_library: fix rules path is list now

* main: better handle multiple rules paths

* main: bail if python 3.6 or below

closes #964

* ida: readme: remove python 3.6 support

* capa2yara: fix rules paths

* render: meta: display rule paths on separate lines

closes #971

* render: verbose: add doc

* verbose: make rule path multiline more concise

* vverbose: don't show examples in output

closes #970

* vverbose: render subscope name, like "basic block:"

closes #963

* build(deps-dev): bump pytest from 7.0.1 to 7.1.1

Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.0.1 to 7.1.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.0.1...7.1.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* ci: build: update pip and setuptools

* ci: build: bump pyinstall to v4.10

* Sync capa rules submodule

* Dotnet mixed mode detect (#969)

* feat: start dotnet detection (#955)

* feat: start dotnet detection

* Apply suggestions from code review

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

* refactor: dn instead of dotnet

* refactor: format branches, extractor reorg

* refactor: format selection and dotnet detect

* feat: get format, arch, os

* refactor: log errors and exceptions

* ci: also test and build for dotnet-main dev

* fix: import path

* fix: circular dep

* fix: remove buf argument
feat: get runtime meta data

* fix: log unsupported runtime error

* fix: type ignore

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

* fix: imports and add tests

* feat: detect mixed mode and tests

* feat: start dotnet detection (#955)

* feat: start dotnet detection

* Apply suggestions from code review

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

* refactor: dn instead of dotnet

* refactor: format branches, extractor reorg

* refactor: format selection and dotnet detect

* feat: get format, arch, os

* refactor: log errors and exceptions

* ci: also test and build for dotnet-main dev

* fix: import path

* fix: circular dep

* fix: remove buf argument
feat: get runtime meta data

* fix: log unsupported runtime error

* fix: type ignore

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

* fix: imports and add tests

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

* test: checkout submodules recursively

Co-authored-by: Capa Bot <capa-dev@mandiant.com>
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-07 17:45:29 +02:00
Capa Bot
4c84a77053 Sync capa rules submodule 2022-04-07 07:50:51 +00:00
Willi Ballenthin
6b810a1f72 ida: insn: look for numbers in displ, not phrase 2022-04-06 15:41:17 -06:00
Willi Ballenthin
c36bde0f2d ida: insn: ignore numbers when SIB present 2022-04-06 15:38:04 -06:00
Willi Ballenthin
1a44dd8a2b insn: better detect offset/numbers 2022-04-06 15:12:59 -06:00
Willi Ballenthin
1c7b6bcf7d fixtures: use function that IDA doesn't recognize as lib func 2022-04-06 15:07:35 -06:00
Willi Ballenthin
e2c6f5e393 ida: insn: use .ea not .va 2022-04-06 15:03:24 -06:00
Willi Ballenthin
85d5043992 changelog 2022-04-06 14:59:24 -06:00
Willi Ballenthin
47dfeafdc8 ida, viv: implement extra offset/number extraction 2022-04-06 14:57:51 -06:00
Willi Ballenthin
b843cef986 tests: add tests for #320 2022-04-06 14:38:56 -06:00
Willi Ballenthin
0e95691cde tests: fixtures: enable assertions against instruction scope 2022-04-06 14:38:33 -06:00
Willi Ballenthin
54aa14c4f5 Merge pull request #975 from mandiant/fix-936
ci: build: bump pyinstall to v4.10
2022-04-06 14:20:21 -06:00
Willi Ballenthin
dfcb3cc2ea ci: build: bump pyinstall to v4.10 2022-04-06 14:17:59 -06:00
Willi Ballenthin
587202ce43 ci: build: update pip and setuptools 2022-04-06 14:03:44 -06:00
Willi Ballenthin
6b2529bc80 Merge pull request #916 from mandiant/dependabot/pip/pytest-7.1.1
build(deps-dev): bump pytest from 7.0.1 to 7.1.1
2022-04-06 13:44:40 -06:00
Willi Ballenthin
52137f310a Merge pull request #974 from mandiant/feature-vverbose-subscope
in vverbose mode, show subscope name
2022-04-06 13:44:15 -06:00
Willi Ballenthin
ad90145aa7 Merge pull request #973 from mandiant/feature-remove-example-vverbose
vverbose: don't show examples in output
2022-04-06 13:42:12 -06:00
Willi Ballenthin
05f7ac0802 Merge pull request #972 from mandiant/feature-many-rule-paths-meta
render: meta: display rule paths on separate lines
2022-04-06 13:41:48 -06:00
Willi Ballenthin
fccca823c5 verbose: make rule path multiline more concise 2022-04-06 13:41:05 -06:00
Willi Ballenthin
441373ea13 vverbose: render subscope name, like "basic block:"
closes #963
2022-04-06 13:33:56 -06:00
Capa Bot
57d2df4922 Sync capa rules submodule 2022-04-06 19:28:26 +00:00
Willi Ballenthin
632e778376 vverbose: don't show examples in output
closes #970
2022-04-06 13:24:36 -06:00
Willi Ballenthin
d47b1503b2 render: verbose: add doc 2022-04-06 13:21:11 -06:00
Willi Ballenthin
938c75737b render: meta: display rule paths on separate lines
closes #971
2022-04-06 13:18:06 -06:00
Willi Ballenthin
55a5d10859 Merge pull request #961 from mandiant/feature-remove-flavors
remove /x32 and /x64 flavors of number and offset features
2022-04-06 12:57:18 -06:00
Willi Ballenthin
0c354cf268 capa2yara: fix rules paths 2022-04-06 12:36:28 -06:00
Willi Ballenthin
485600801c ida: readme: remove python 3.6 support 2022-04-06 12:16:06 -06:00
Willi Ballenthin
4916933139 main: bail if python 3.6 or below
closes #964
2022-04-06 12:14:53 -06:00
Capa Bot
73f1eb9c30 Sync capa rules submodule 2022-04-06 18:08:02 +00:00
Willi Ballenthin
e788384d42 main: better handle multiple rules paths 2022-04-06 12:05:01 -06:00
Capa Bot
633d8df1a4 Sync capa-testfiles submodule 2022-04-06 17:21:09 +00:00
Willi Ballenthin
aff72ad983 capa_as_library: fix rules path is list now 2022-04-06 11:07:34 -06:00
Willi Ballenthin
c9763c4d70 Merge branch 'master' into feature-remove-flavors 2022-04-06 11:05:05 -06:00
Capa Bot
931a13e505 Sync capa rules submodule 2022-04-06 17:04:16 +00:00
Moritz Raabe
97e76a88e3 fix: imports and add tests 2022-04-06 17:30:51 +02:00
Moritz
b5be876e61 feat: start dotnet detection (#955)
* feat: start dotnet detection

* Apply suggestions from code review

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

* refactor: dn instead of dotnet

* refactor: format branches, extractor reorg

* refactor: format selection and dotnet detect

* feat: get format, arch, os

* refactor: log errors and exceptions

* ci: also test and build for dotnet-main dev

* fix: import path

* fix: circular dep

* fix: remove buf argument
feat: get runtime meta data

* fix: log unsupported runtime error

* fix: type ignore

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2022-04-06 11:33:14 +02:00
Willi Ballenthin
7370a8f296 changelog 2022-04-05 17:21:04 -06:00
Willi Ballenthin
11b773573e lint: fix rules path 2022-04-05 17:17:44 -06:00
Willi Ballenthin
67dc2cb0fa main: fix removal of default rules path 2022-04-05 17:17:35 -06:00
Willi Ballenthin
bad9ecf3b1 main: accept multiple paths to rules 2022-04-05 17:14:53 -06:00
Willi Ballenthin
ef835649fd vverbose: show lib rule matches 2022-04-05 16:57:36 -06:00
Willi Ballenthin
e9bb56f3cf API: better support A/W functions 2022-04-05 14:54:15 -06:00
Willi Ballenthin
58acc9c2b7 rules: fix max operand index (4) 2022-04-05 14:53:58 -06:00
Willi Ballenthin
f923a4ea9b linter: accept instruction scope 2022-04-05 12:24:41 -06:00
Willi Ballenthin
5957dfecf0 Merge branch 'feature-remove-flavors' of github.com:mandiant/capa into feature-remove-flavors 2022-04-05 10:41:41 -06:00
Willi Ballenthin
aee61b35e4 *: remove more references to /x32 and /x64 2022-04-05 10:41:03 -06:00
Willi Ballenthin
169d5ab826 Merge branch 'master' into feature-remove-flavors 2022-04-05 10:37:18 -06:00
Willi Ballenthin
de312d87dc Merge pull request #960 from mandiant/feature-py37
upgrade min python version to 3.7
2022-04-05 10:36:33 -06:00
Willi Ballenthin
ecabd557a7 *: remove /x32 and /x64 flavors from number and offset features 2022-04-05 10:35:41 -06:00
Willi Ballenthin
f246a01484 changelog 2022-04-05 10:24:55 -06:00
Willi Ballenthin
0617b87f36 ci: no longer test against py3.6 2022-04-05 10:19:09 -06:00
Willi Ballenthin
715ac64ae6 changelog 2022-04-05 10:19:04 -06:00
Willi Ballenthin
78c0afe006 setup: min python version is now 3.7 2022-04-05 10:18:55 -06:00
Willi Ballenthin
df03932f89 gitignore 2022-04-04 16:54:51 -06:00
dependabot[bot]
15196c847a build(deps-dev): bump pytest from 7.0.1 to 7.1.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.0.1 to 7.1.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.0.1...7.1.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-04 22:43:41 +00:00
Willi Ballenthin
b2b4471851 Merge pull request #930 from mandiant/feature-insn-scope
feature: instruction scope
2022-04-04 16:42:56 -06:00
Willi Ballenthin
5ffb73c5f5 ida: insn: extract operand number and offset features 2022-04-04 15:13:43 -06:00
Willi Ballenthin
ef93fcc89e tests: smda: xfail operand number/offset features 2022-04-04 12:05:15 -06:00
Willi Ballenthin
0af60d9a7e freeze: fix mypy 2022-04-04 12:01:13 -06:00
Willi Ballenthin
750803c3cc freeze: register operand features 2022-04-04 11:57:02 -06:00
Willi Ballenthin
b318b0a288 freeze: fix freeze_deserialize for features with multiple args 2022-04-04 11:56:47 -06:00
Willi Ballenthin
2989af0a3f features: use ABC to denote abstract classes 2022-04-04 11:49:51 -06:00
Moritz
3f168772aa Merge pull request #934 from mandiant/dependabot/pip/types-colorama-0.4.10
build(deps-dev): bump types-colorama from 0.4.9 to 0.4.10
2022-04-04 17:42:16 +02:00
Moritz
2ba25f096d Merge pull request #935 from mandiant/dependabot/pip/types-requests-2.27.16
build(deps-dev): bump types-requests from 2.27.15 to 2.27.16
2022-04-04 17:42:02 +02:00
Moritz
6d35e19571 Merge pull request #933 from mandiant/dependabot/pip/tqdm-4.64.0
build(deps): bump tqdm from 4.63.1 to 4.64.0
2022-04-04 17:41:56 +02:00
dependabot[bot]
0d9583f7e7 build(deps-dev): bump types-requests from 2.27.15 to 2.27.16
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.15 to 2.27.16.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-04 14:12:27 +00:00
dependabot[bot]
fe6b18135c build(deps-dev): bump types-colorama from 0.4.9 to 0.4.10
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.9 to 0.4.10.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-04 14:12:24 +00:00
dependabot[bot]
e89fe57def build(deps): bump tqdm from 4.63.1 to 4.64.0
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.63.1 to 4.64.0.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.63.1...v4.64.0)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-04 14:12:21 +00:00
Willi Ballenthin
85b1d50945 isort 2022-03-31 10:40:48 -06:00
Willi Ballenthin
856443319c viv: insn: fix OperandNumber reference 2022-03-31 10:39:18 -06:00
Willi Ballenthin
9da4ff10da *: rename OperandImmediate to OperandNumber 2022-03-31 10:37:06 -06:00
Willi Ballenthin
76831e9b9d changelog 2022-03-30 13:20:51 -06:00
Willi Ballenthin
997daf537e viv: insn: extract OperandOffset and OperandImmediate 2022-03-30 13:14:08 -06:00
Willi Ballenthin
c7aadca25c tests: demonstrate OperandOffset and OperandImmediate 2022-03-30 13:13:50 -06:00
Willi Ballenthin
6cbbd4d97f rules: parse OperandOffset and OperandImmediate features 2022-03-30 13:13:30 -06:00
Willi Ballenthin
e4c5ec278d features: insn: define OperandImmediate and OperandOffset 2022-03-30 13:13:07 -06:00
Willi Ballenthin
cce1e41519 formatting 2022-03-30 13:12:49 -06:00
Willi Ballenthin
b942050c4e features: viv: factor out operand feature extraction 2022-03-30 09:58:08 -06:00
Willi Ballenthin
d8d671e36f rules: add global scope features to file scope 2022-03-30 09:40:43 -06:00
Willi Ballenthin
49adb8de0c pep8 2022-03-29 13:00:28 -06:00
Willi Ballenthin
fb6b60bee3 tests: add tests demonstrating instruction (sub)scope matching 2022-03-29 12:58:38 -06:00
Willi Ballenthin
e0fca277f2 rules: update valid features per scope 2022-03-29 12:58:27 -06:00
Willi Ballenthin
0effb5f8b0 changelog 2022-03-29 12:33:55 -06:00
Willi Ballenthin
1839746bf8 main: factor out matching at instruction scope 2022-03-29 12:29:54 -06:00
Willi Ballenthin
1a28c324f1 rules: doc 2022-03-29 12:26:39 -06:00
Willi Ballenthin
c1b28f58d0 rules: don't use global features to downselect rules
closes #931
2022-03-29 12:25:27 -06:00
Willi Ballenthin
565e4e0a2f Merge branch 'feature-insn-scope' of github.com:mandiant/capa into feature-insn-scope 2022-03-29 11:52:45 -06:00
Willi Ballenthin
7487da89a1 Merge branch 'master' into feature-insn-scope 2022-03-29 11:51:14 -06:00
Willi Ballenthin
fe5d88585c setup: bump black to 22.3.0 to fix CI 2022-03-29 11:40:34 -06:00
Willi Ballenthin
bd6e62e9bf Update scripts/lint.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2022-03-29 11:26:21 -06:00
Willi Ballenthin
b76930d2a3 main: split out basic block feature, match extraction 2022-03-28 13:47:53 -06:00
Willi Ballenthin
00d439f681 main: rename find_code_capabilities 2022-03-28 13:29:06 -06:00
Willi Ballenthin
963cfbf380 pep8 2022-03-28 13:17:35 -06:00
Willi Ballenthin
031ea167e8 add pycodestyle config 2022-03-28 13:17:18 -06:00
Willi Ballenthin
dde52f2bc8 pep8 2022-03-28 13:04:44 -06:00
Willi Ballenthin
46cc681eba tests: demonstrate instruct subscope rule extraction 2022-03-28 13:04:13 -06:00
Willi Ballenthin
b0619f4f01 rules: index instruction rules in ruleset 2022-03-28 13:03:58 -06:00
Willi Ballenthin
2baf05acdb rules: parse instruction subscope with implied AND 2022-03-28 12:55:09 -06:00
Willi Ballenthin
890870bf45 rules: let subscope blocks have descriptions 2022-03-28 12:54:54 -06:00
Willi Ballenthin
9da9c3aceb rules: add valid features for insn scope 2022-03-28 12:40:10 -06:00
Willi Ballenthin
c8fedb0f70 gitignore 2022-03-28 12:39:58 -06:00
Willi Ballenthin
a203f56bdb rules: add new scope "instruction" 2022-03-28 12:14:07 -06:00
Willi Ballenthin
18880c40d5 Merge pull request #927 from mandiant/dependabot/pip/mypy-0.942
build(deps-dev): bump mypy from 0.941 to 0.942
2022-03-28 11:26:06 -06:00
Willi Ballenthin
bd62661ef3 Merge pull request #928 from mandiant/dependabot/pip/types-requests-2.27.15
build(deps-dev): bump types-requests from 2.27.12 to 2.27.15
2022-03-28 11:25:57 -06:00
Willi Ballenthin
8d285c03ad Merge pull request #929 from mandiant/dependabot/pip/tqdm-4.63.1
build(deps): bump tqdm from 4.63.0 to 4.63.1
2022-03-28 11:25:25 -06:00
dependabot[bot]
7a4ee78805 build(deps): bump tqdm from 4.63.0 to 4.63.1
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.63.0 to 4.63.1.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.63.0...v4.63.1)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 14:13:45 +00:00
dependabot[bot]
6105d2a36c build(deps-dev): bump types-requests from 2.27.12 to 2.27.15
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.12 to 2.27.15.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 14:13:39 +00:00
dependabot[bot]
7db90ba35e build(deps-dev): bump mypy from 0.941 to 0.942
Bumps [mypy](https://github.com/python/mypy) from 0.941 to 0.942.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.941...v0.942)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 14:13:37 +00:00
Mike Hunhoff
fb34b1674b improve handling _ prefix added to library functions as compile/link artifact (#924) 2022-03-25 13:34:39 -06:00
Capa Bot
eaf978da0a Sync capa rules submodule 2022-03-24 09:43:38 +00:00
Capa Bot
ecea572192 Sync capa-testfiles submodule 2022-03-24 09:30:26 +00:00
Capa Bot
5552baa5e2 Sync capa rules submodule 2022-03-24 08:16:48 +00:00
Capa Bot
3b86ccc1a4 Sync capa rules submodule 2022-03-23 17:57:09 +00:00
Mike Hunhoff
8fd81d1098 Merge pull request #922 from mandiant/pin-smda-version-171
update pinned smda version
2022-03-22 12:46:35 -06:00
Mike Hunhoff
b7badede86 update pinned smda version 2022-03-22 12:25:41 -06:00
Mike Hunhoff
4c4e633395 Merge pull request #919 from mandiant/fix/917
fixes #917
2022-03-22 07:15:40 -06:00
Capa Bot
1cd5e89f85 Sync capa-testfiles submodule 2022-03-22 07:22:11 +00:00
Michael Hunhoff
768050f36c update CHANGELOG 2022-03-21 15:37:21 -06:00
Michael Hunhoff
f7f286db6c merge upstream 2022-03-21 15:35:49 -06:00
Mike Hunhoff
6d2ec59653 Merge pull request #918 from mandiant/fix/911
fixes #911
2022-03-21 15:33:45 -06:00
Michael Hunhoff
924d0111fd fixes #917 2022-03-21 15:28:39 -06:00
Michael Hunhoff
fe87838dbe fixes #911 2022-03-21 13:48:41 -06:00
Willi Ballenthin
1b2f0fc85d Merge pull request #913 from mandiant/dependabot/pip/types-tabulate-0.8.6
build(deps-dev): bump types-tabulate from 0.8.5 to 0.8.6
2022-03-21 10:36:55 -06:00
dependabot[bot]
e3bec5f186 build(deps-dev): bump types-tabulate from 0.8.5 to 0.8.6
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.5 to 0.8.6.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-21 16:36:24 +00:00
Willi Ballenthin
729b459701 Merge pull request #914 from mandiant/dependabot/pip/types-pyyaml-6.0.5
build(deps-dev): bump types-pyyaml from 6.0.4 to 6.0.5
2022-03-21 10:35:53 -06:00
Willi Ballenthin
1609bd5d07 Merge pull request #915 from mandiant/dependabot/pip/mypy-0.941
build(deps-dev): bump mypy from 0.940 to 0.941
2022-03-21 10:35:07 -06:00
dependabot[bot]
78222a530c build(deps-dev): bump types-pyyaml from 6.0.4 to 6.0.5
Bumps [types-pyyaml](https://github.com/python/typeshed) from 6.0.4 to 6.0.5.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-21 16:34:23 +00:00
dependabot[bot]
6613ee3c87 build(deps-dev): bump mypy from 0.940 to 0.941
Bumps [mypy](https://github.com/python/mypy) from 0.940 to 0.941.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.940...v0.941)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-21 16:34:23 +00:00
Willi Ballenthin
356b2f5ffb Merge pull request #912 from mandiant/dependabot/pip/types-colorama-0.4.9
build(deps-dev): bump types-colorama from 0.4.8 to 0.4.9
2022-03-21 10:33:37 -06:00
dependabot[bot]
a52cc7280f build(deps-dev): bump types-colorama from 0.4.8 to 0.4.9
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.8 to 0.4.9.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-21 14:13:40 +00:00
Capa Bot
0d38e3065c Sync capa rules submodule 2022-03-16 09:43:58 +00:00
Willi Ballenthin
3d13d501e7 Merge pull request #907 from mandiant/dependabot/pip/mypy-0.940
build(deps-dev): bump mypy from 0.931 to 0.940
2022-03-14 10:49:05 -06:00
Willi Ballenthin
ccf1f6205c Merge pull request #908 from mandiant/dependabot/pip/types-requests-2.27.12
build(deps-dev): bump types-requests from 2.27.11 to 2.27.12
2022-03-14 10:48:40 -06:00
dependabot[bot]
8d2b6df385 build(deps-dev): bump types-requests from 2.27.11 to 2.27.12
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.11 to 2.27.12.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-14 14:14:24 +00:00
dependabot[bot]
62fd13c892 build(deps-dev): bump mypy from 0.931 to 0.940
Bumps [mypy](https://github.com/python/mypy) from 0.931 to 0.940.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.931...v0.940)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-14 14:14:21 +00:00
Capa Bot
cbf9f321c6 Sync capa-testfiles submodule 2022-03-14 10:18:05 +00:00
Moritz
c975305e95 Merge pull request #906 from mandiant/ci/remove-windows-2016
remove windows-2016
2022-03-14 10:18:11 +01:00
Willi Ballenthin
8afd12103d ci: build: try to use windows-2022 2022-03-11 17:40:35 -07:00
Moritz
5d106afca6 remove windows-2016 2022-03-11 08:38:09 +01:00
Capa Bot
8e43a23766 Sync capa rules submodule 2022-03-10 18:21:36 +00:00
Moritz
d9d72ad8df Merge pull request #905 from mandiant/v320
release v3.2.0
2022-03-03 19:59:17 +01:00
Moritz Raabe
1c5af81a4e release v3.2.0 2022-03-03 10:45:43 +01:00
Capa Bot
014fc4cda9 Sync capa rules submodule 2022-03-03 09:26:55 +00:00
Moritz
f29992741d Merge pull request #904 from mandiant/bump-viv-utils-vivisect
bump vivisect 1.0.7 and viv-utils 0.6.11
2022-03-02 08:59:21 +01:00
Moritz Raabe
5fa5f08607 bump vivisect 1.0.7 and viv-utils 0.6.11 2022-03-02 07:51:29 +01:00
Moritz
d4921c4a2f Merge pull request #902 from mandiant/feature/call5-ida
Feature/call5 ida
2022-03-01 09:05:33 +01:00
Moritz
64238062ca Merge pull request #901 from uckelman-sf/use_stdlib_typing
Don't require typing package; it's in the stdlib now
2022-03-01 09:00:25 +01:00
Moritz Raabe
00f977fff9 add call $+5 characteristic for IDA extractor 2022-03-01 08:50:06 +01:00
Moritz
c7ae2cd540 Merge pull request #899 from kn0wl3dge/feature/366-shellcode_obfs_call
Add characteristic "call $+5" feature with support for vivisect and smda
2022-03-01 08:48:50 +01:00
Moritz
293d88b1b9 Merge pull request #900 from mandiant/dependabot/pip/tqdm-4.63.0
build(deps): bump tqdm from 4.62.3 to 4.63.0
2022-02-28 22:28:52 +01:00
Joel Uckelman
fa2d19a5ca Update change log. 2022-02-28 16:43:18 +00:00
Joel Uckelman
f0f22041ca Remove requirement for separate typing package; typing is in the Python
stdlib from 3.5, and we require >= 3.6. From 3.7, installing the typing
package causes import failures.
2022-02-28 14:55:18 +00:00
dependabot[bot]
321316f99f build(deps): bump tqdm from 4.62.3 to 4.63.0
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.62.3 to 4.63.0.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.62.3...v4.63.0)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-28 14:09:59 +00:00
Baptistin Boilot
4d915020a8 extractor: add characteristic(call $+5) feature extraction for vivisect and smda 2022-02-27 18:15:25 +01:00
Moritz
350eff27b7 Merge pull request #898 from mandiant/dependabot/pip/types-requests-2.27.11
build(deps-dev): bump types-requests from 2.27.10 to 2.27.11
2022-02-23 08:54:56 +01:00
dependabot[bot]
f9732db799 build(deps-dev): bump types-requests from 2.27.10 to 2.27.11
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.10 to 2.27.11.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-22 18:29:53 +00:00
Moritz
73a7842a85 Merge pull request #897 from mandiant/dependabot/pip/types-requests-2.27.10
build(deps-dev): bump types-requests from 2.27.9 to 2.27.10
2022-02-22 19:26:01 +01:00
dependabot[bot]
b13a402675 build(deps-dev): bump types-requests from 2.27.9 to 2.27.10
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.9 to 2.27.10.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-21 14:11:58 +00:00
Moritz
915cd5e4bc Merge pull request #896 from mandiant/dependabot/pip/pytest-7.0.1
build(deps-dev): bump pytest from 7.0.0 to 7.0.1
2022-02-15 10:23:25 +01:00
Moritz
151adfd5ed Merge pull request #894 from mandiant/dependabot/pip/ruamel-yaml-0.17.21
build(deps): bump ruamel-yaml from 0.17.20 to 0.17.21
2022-02-15 10:23:14 +01:00
Moritz
37519a038b Merge pull request #895 from mandiant/dependabot/pip/types-requests-2.27.9
build(deps-dev): bump types-requests from 2.27.8 to 2.27.9
2022-02-15 10:22:57 +01:00
dependabot[bot]
d0cc1b0b1d build(deps-dev): bump pytest from 7.0.0 to 7.0.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.0.0...7.0.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 14:14:42 +00:00
dependabot[bot]
869ad9d561 build(deps-dev): bump types-requests from 2.27.8 to 2.27.9
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.8 to 2.27.9.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 14:14:38 +00:00
dependabot[bot]
b31a4d6242 build(deps): bump ruamel-yaml from 0.17.20 to 0.17.21
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.20 to 0.17.21.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 14:14:34 +00:00
Moritz
439a855383 Merge pull request #893 from re-fox/master
Update capa_as_library.py
2022-02-14 10:36:42 +01:00
re-fox
37f51690d0 Update capa_as_library.py 2022-02-13 13:09:58 -05:00
Moritz
1bd807a1a0 Merge pull request #890 from mandiant/dependabot/pip/pyelftools-0.28
build(deps): bump pyelftools from 0.27 to 0.28
2022-02-07 21:25:23 +01:00
Moritz
ac6fef2e29 Merge pull request #889 from mandiant/dependabot/pip/pytest-7.0.0
build(deps-dev): bump pytest from 6.2.5 to 7.0.0
2022-02-07 21:24:52 +01:00
dependabot[bot]
e873086ddf build(deps): bump pyelftools from 0.27 to 0.28
Bumps [pyelftools](https://github.com/eliben/pyelftools) from 0.27 to 0.28.
- [Release notes](https://github.com/eliben/pyelftools/releases)
- [Changelog](https://github.com/eliben/pyelftools/blob/master/CHANGES)
- [Commits](https://github.com/eliben/pyelftools/compare/v0.27...v0.28)

---
updated-dependencies:
- dependency-name: pyelftools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-07 14:11:51 +00:00
dependabot[bot]
dd6159b062 build(deps-dev): bump pytest from 6.2.5 to 7.0.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.5 to 7.0.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.5...7.0.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-07 14:11:46 +00:00
Willi Ballenthin
7511563865 Merge pull request #888 from kn0wl3dge/fix/879_mbc_names
Add MBC names and IDs to the linting script
2022-02-06 11:49:58 -07:00
Capa Bot
9923216558 Sync capa rules submodule 2022-02-06 18:49:26 +00:00
Baptistin Boilot
d026d21073 linter: add MBC names and IDs to the linting script 2022-02-06 11:47:49 +01:00
Capa Bot
5bfe706b56 Sync capa rules submodule 2022-02-04 19:27:03 +00:00
Willi Ballenthin
2407015620 Merge pull request #887 from mandiant/dependabot/pip/types-colorama-0.4.8
build(deps-dev): bump types-colorama from 0.4.7 to 0.4.8
2022-01-31 12:55:33 -07:00
Willi Ballenthin
a8dd9d4bfd Merge branch 'master' into dependabot/pip/types-colorama-0.4.8 2022-01-31 12:55:27 -07:00
Willi Ballenthin
8d247bd1b6 Merge pull request #886 from mandiant/dependabot/pip/types-psutil-5.8.20
build(deps-dev): bump types-psutil from 5.8.19 to 5.8.20
2022-01-31 11:56:56 -07:00
Willi Ballenthin
533666d40c Merge branch 'master' into dependabot/pip/types-psutil-5.8.20 2022-01-31 11:56:50 -07:00
Willi Ballenthin
b85ee0b7a0 Merge pull request #885 from mandiant/dependabot/pip/black-22.1.0
build(deps-dev): bump black from 21.12b0 to 22.1.0
2022-01-31 11:56:25 -07:00
dependabot[bot]
9466038e62 build(deps-dev): bump types-colorama from 0.4.7 to 0.4.8
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.7 to 0.4.8.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-31 18:53:47 +00:00
dependabot[bot]
e5eb9bf4f2 build(deps-dev): bump types-psutil from 5.8.19 to 5.8.20
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.19 to 5.8.20.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-31 18:53:45 +00:00
Willi Ballenthin
a3615ad0d3 Merge pull request #884 from mandiant/dependabot/pip/types-requests-2.27.8
build(deps-dev): bump types-requests from 2.27.7 to 2.27.8
2022-01-31 11:53:32 -07:00
Willi Ballenthin
2f6b5566d8 Merge pull request #883 from mandiant/dependabot/pip/types-pyyaml-6.0.4
build(deps-dev): bump types-pyyaml from 6.0.3 to 6.0.4
2022-01-31 11:53:20 -07:00
dependabot[bot]
79b40cab14 build(deps-dev): bump black from 21.12b0 to 22.1.0
Bumps [black](https://github.com/psf/black) from 21.12b0 to 22.1.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits/22.1.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-31 18:53:12 +00:00
Willi Ballenthin
6276b5d79e Merge pull request #882 from mandiant/dependabot/pip/smda-1.7.0
build(deps): bump smda from 1.6.2 to 1.7.0
2022-01-31 11:52:52 -07:00
dependabot[bot]
fac7ec1e00 build(deps-dev): bump types-requests from 2.27.7 to 2.27.8
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.7 to 2.27.8.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-31 14:15:22 +00:00
dependabot[bot]
356e5babd0 build(deps-dev): bump types-pyyaml from 6.0.3 to 6.0.4
Bumps [types-pyyaml](https://github.com/python/typeshed) from 6.0.3 to 6.0.4.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-31 14:15:20 +00:00
dependabot[bot]
b2de090581 build(deps): bump smda from 1.6.2 to 1.7.0
Bumps [smda](https://github.com/danielplohmann/smda) from 1.6.2 to 1.7.0.
- [Release notes](https://github.com/danielplohmann/smda/releases)
- [Commits](https://github.com/danielplohmann/smda/commits)

---
updated-dependencies:
- dependency-name: smda
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-31 14:15:18 +00:00
Willi Ballenthin
364ec1fa2c Merge pull request #880 from mandiant/dependabot/pip/types-requests-2.27.7
build(deps-dev): bump types-requests from 2.27.3 to 2.27.7
2022-01-26 08:50:16 -07:00
Willi Ballenthin
afc64b8287 Merge branch 'master' into dependabot/pip/types-requests-2.27.7 2022-01-26 08:50:08 -07:00
dependabot[bot]
5953f86c7e build(deps-dev): bump types-requests from 2.27.3 to 2.27.7
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.3 to 2.27.7.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-26 09:33:05 +00:00
Moritz
cfad012f92 Merge pull request #875 from kn0wl3dge/feature/103-validate_attck_mbc
Validate ATT&CK/MBC categories and IDs
2022-01-26 10:32:44 +01:00
Baptistin Boilot
2e8c2f40d6 linter: update linter-data.json with mitre att&ck references only 2022-01-26 00:11:01 +01:00
Baptistin Boilot
377c805fe7 linter: improve linter-data.json opening and add documentation
- Open linter-data.json in byte mode
- Add a comment explaining how to invoke the script
2022-01-24 22:48:59 +01:00
Capa Bot
bbb97da3fc Sync capa rules submodule 2022-01-24 17:10:29 +00:00
Capa Bot
78fde6f812 Sync capa rules submodule 2022-01-24 16:57:32 +00:00
Capa Bot
09081c0d2d Sync capa rules submodule 2022-01-24 16:51:22 +00:00
Willi Ballenthin
abeb507ea0 Merge pull request #876 from mandiant/dependabot/pip/types-colorama-0.4.7
build(deps-dev): bump types-colorama from 0.4.6 to 0.4.7
2022-01-24 09:49:41 -07:00
dependabot[bot]
d8c2759a72 build(deps-dev): bump types-colorama from 0.4.6 to 0.4.7
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.6 to 0.4.7.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-24 14:12:06 +00:00
Capa Bot
f0fc39e1d0 Sync capa-testfiles submodule 2022-01-24 13:37:25 +00:00
Capa Bot
81d604d85a Sync capa-testfiles submodule 2022-01-24 11:00:44 +00:00
Baptistin Boilot
0c978a8def scripts: fix typing issue in setup-linter-dependencies 2022-01-22 17:18:02 +01:00
Baptistin Boilot
c6ac239c5a linter: fix imports and codingstyle 2022-01-22 16:45:50 +01:00
Baptistin Boilot
370ad6cdd7 docs: add code documentation and update changelog 2022-01-22 16:45:49 +01:00
Baptistin Boilot
2bcd725e04 linter: add the possibility to enable or disable mbc and att&ck linting 2022-01-22 16:45:47 +01:00
Baptistin Boilot
0b487546bb linter: add mbc data extractor and linter 2022-01-22 16:45:46 +01:00
Baptistin Boilot
67d8d832c9 linter: refactor att&ck linter and add attck json data 2022-01-22 16:45:35 +01:00
Baptistin Boilot
fa99782f02 linter: add a linter rule that checks for invalid att&ck technique 2022-01-22 16:44:07 +01:00
Baptistin Boilot
60a30518bc linter: add mitre att&ck ttps extraction script 2022-01-22 16:43:42 +01:00
dependabot[bot]
122fb5f9f1 build(deps-dev): bump types-termcolor from 1.1.2 to 1.1.3
Bumps [types-termcolor](https://github.com/python/typeshed) from 1.1.2 to 1.1.3.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-termcolor
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-22 16:43:37 +01:00
Willi Ballenthin
5daf444c8a Merge pull request #871 from mandiant/dependabot/pip/types-termcolor-1.1.3
build(deps-dev): bump types-termcolor from 1.1.2 to 1.1.3
2022-01-17 14:02:51 -07:00
Willi Ballenthin
41fbb8cdc4 Merge pull request #872 from mandiant/dependabot/pip/types-colorama-0.4.6
build(deps-dev): bump types-colorama from 0.4.5 to 0.4.6
2022-01-17 14:02:37 -07:00
dependabot[bot]
edfb69f8e9 build(deps-dev): bump types-colorama from 0.4.5 to 0.4.6
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.5 to 0.4.6.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-17 14:18:10 +00:00
dependabot[bot]
14b0d8e7a6 build(deps-dev): bump types-termcolor from 1.1.2 to 1.1.3
Bumps [types-termcolor](https://github.com/python/typeshed) from 1.1.2 to 1.1.3.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-termcolor
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-17 14:18:07 +00:00
Willi Ballenthin
a085ff855d Merge pull request #868 from mandiant/fix/867
elf: parse section headers looking for Linux notes, too
2022-01-14 11:41:22 -07:00
William Ballenthin
b392b48b28 black 2022-01-13 15:24:58 -07:00
William Ballenthin
93355a6884 changelog 2022-01-13 15:23:17 -07:00
William Ballenthin
b28b30eb0f elf: parse section headers looking for Linux notes, too
closes #867
2022-01-13 15:21:23 -07:00
Willi Ballenthin
c0851fc643 Merge pull request #863 from mandiant/v3.1.0
version: v3.1.0
2022-01-12 14:18:22 -07:00
Willi Ballenthin
de7592b351 changelog: add additional contributor 2022-01-11 14:29:15 -07:00
Willi Ballenthin
5530bbad53 Update CHANGELOG.md
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2022-01-11 14:28:17 -07:00
Willi Ballenthin
4f0067e408 Update CHANGELOG.md
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2022-01-11 14:27:59 -07:00
Willi Ballenthin
b444c28a19 changelog: fix format 2022-01-11 10:05:40 -07:00
Willi Ballenthin
a4cc409c95 Update capa/version.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2022-01-10 12:39:07 -07:00
Moritz
fcb08501c0 Merge pull request #865 from mandiant/mr-tz-patch-1
Update global_.py
2022-01-10 19:21:24 +01:00
Moritz
cb2d00cefc Update global_.py 2022-01-10 19:04:52 +01:00
Willi Ballenthin
1cb9fc8a40 Merge pull request #864 from doomedraven/patch-1
Fix deprication warning from IDA
2022-01-10 10:52:10 -07:00
doomedraven
85cfc04bdb Fix deprication warning from IDA
```
    if info.procName == "metapc" and info.is_64bit():
```
Please use "procname" instead of "procName" ("procName" is kept for backward-compatibility, and will be removed soon.)
2022-01-10 18:37:59 +01:00
Willi Ballenthin
6555a3604f changelog: intro section 2022-01-10 09:49:00 -07:00
Willi Ballenthin
a97262d022 changelog: v3.1.0 2022-01-10 09:39:46 -07:00
Willi Ballenthin
8ad54271e9 version: v3.1.0 2022-01-10 09:33:39 -07:00
Willi Ballenthin
e5b9a20d09 changelog: add rule changes and contributors 2022-01-10 09:32:49 -07:00
Willi Ballenthin
0d37d182ea changelog: add some additional entries 2022-01-10 09:26:14 -07:00
Willi Ballenthin
6690634a3f Merge pull request #858 from mandiant/dependabot/pip/types-pyyaml-6.0.3
build(deps-dev): bump types-pyyaml from 6.0.1 to 6.0.3
2022-01-10 08:26:25 -07:00
dependabot[bot]
8f3730bae3 build(deps-dev): bump types-pyyaml from 6.0.1 to 6.0.3
Bumps [types-pyyaml](https://github.com/python/typeshed) from 6.0.1 to 6.0.3.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-10 15:25:42 +00:00
Willi Ballenthin
8f4e726774 Merge pull request #859 from mandiant/dependabot/pip/types-tabulate-0.8.5
build(deps-dev): bump types-tabulate from 0.8.4 to 0.8.5
2022-01-10 08:25:12 -07:00
Willi Ballenthin
5b8eda0f08 Merge pull request #861 from mandiant/dependabot/pip/mypy-0.931
build(deps-dev): bump mypy from 0.930 to 0.931
2022-01-10 08:24:59 -07:00
Willi Ballenthin
f5f62bbd71 Merge pull request #862 from mandiant/dependabot/pip/types-psutil-5.8.19
build(deps-dev): bump types-psutil from 5.8.17 to 5.8.19
2022-01-10 08:24:41 -07:00
dependabot[bot]
24c3edc7ec build(deps-dev): bump types-psutil from 5.8.17 to 5.8.19
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.17 to 5.8.19.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-10 14:18:21 +00:00
dependabot[bot]
0e3d46ef5e build(deps-dev): bump mypy from 0.930 to 0.931
Bumps [mypy](https://github.com/python/mypy) from 0.930 to 0.931.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.930...v0.931)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-10 14:18:19 +00:00
dependabot[bot]
a3546b65f7 build(deps-dev): bump types-tabulate from 0.8.4 to 0.8.5
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.4 to 0.8.5.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-10 14:18:09 +00:00
Willi Ballenthin
01b694b6ab Merge pull request #851 from kn0wl3dge/fix/430
smda: fix negative number extraction
2022-01-03 12:08:41 -07:00
Moritz
3598f83091 Merge pull request #856 from mandiant/dependabot/pip/psutil-5.9.0
build(deps-dev): bump psutil from 5.8.0 to 5.9.0
2022-01-03 17:33:56 +01:00
Moritz
2085dd7b02 Merge pull request #853 from mandiant/dependabot/pip/ruamel-yaml-0.17.20
build(deps): bump ruamel-yaml from 0.17.19 to 0.17.20
2022-01-03 17:33:40 +01:00
Moritz
65d916332d Merge pull request #855 from mandiant/dependabot/pip/types-psutil-5.8.17
build(deps-dev): bump types-psutil from 5.8.16 to 5.8.17
2022-01-03 17:33:26 +01:00
Moritz
1937efce88 Merge pull request #852 from mandiant/dependabot/pip/types-tabulate-0.8.4
build(deps-dev): bump types-tabulate from 0.8.3 to 0.8.4
2022-01-03 17:33:19 +01:00
Moritz
501d607b3a Merge pull request #854 from mandiant/dependabot/pip/types-colorama-0.4.5
build(deps-dev): bump types-colorama from 0.4.4 to 0.4.5
2022-01-03 17:33:07 +01:00
dependabot[bot]
7d6670c59e build(deps-dev): bump psutil from 5.8.0 to 5.9.0
Bumps [psutil](https://github.com/giampaolo/psutil) from 5.8.0 to 5.9.0.
- [Release notes](https://github.com/giampaolo/psutil/releases)
- [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst)
- [Commits](https://github.com/giampaolo/psutil/compare/release-5.8.0...release-5.9.0)

---
updated-dependencies:
- dependency-name: psutil
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 14:11:03 +00:00
dependabot[bot]
fe608db16a build(deps-dev): bump types-psutil from 5.8.16 to 5.8.17
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.16 to 5.8.17.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 14:10:58 +00:00
dependabot[bot]
be1f313d57 build(deps-dev): bump types-colorama from 0.4.4 to 0.4.5
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.4 to 0.4.5.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 14:10:55 +00:00
dependabot[bot]
cb77c55d2c build(deps): bump ruamel-yaml from 0.17.19 to 0.17.20
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.19 to 0.17.20.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 14:10:53 +00:00
dependabot[bot]
417aa35c60 build(deps-dev): bump types-tabulate from 0.8.3 to 0.8.4
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.3 to 0.8.4.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 14:10:46 +00:00
Baptistin Boilot
18877eb676 changelog: add fixed issue 2021-12-31 21:14:56 +01:00
Baptistin Boilot
a9670c9510 smda: fix number extractor to return only unsigned values
SmdaInstruction operands are python `str` objects. SMDA number operands are signed integers.
This commit adds a converter to the SMDA number extractor.
The goal is to convert any signed number to the two’s complement representation with the correct bitness.
2021-12-31 20:10:36 +01:00
Baptistin Boilot
8474369575 tests: add fixtures for two's complement numbers
Add fixtures to validate the following number features:
- number(0x0): to check feature extraction for null number
- number(0xFFFFFFFF): to check feature extraction for -1 number
- number(0xFFFFFFF0): to check feature extraction for negative number (-0x10 in this case)
2021-12-31 20:08:56 +01:00
Baptistin Boilot
4739d121a2 scripts: add backend parameter (-b) to show-features.py 2021-12-31 20:07:34 +01:00
Mike Hunhoff
e47f5a2548 Merge pull request #849 from mandiant/fix/845
capa explorer: updating supported IDA versions
2021-12-31 10:48:53 -07:00
Willi Ballenthin
51f5628383 Merge pull request #847 from mandiant/dependabot/pip/ruamel-yaml-0.17.19
build(deps): bump ruamel-yaml from 0.17.17 to 0.17.19
2021-12-29 09:44:24 -07:00
Willi Ballenthin
aa67a1b285 Merge pull request #846 from mandiant/dependabot/pip/types-psutil-5.8.16
build(deps-dev): bump types-psutil from 5.8.15 to 5.8.16
2021-12-29 09:44:15 -07:00
Willi Ballenthin
d22e51fd84 Merge pull request #848 from mandiant/dependabot/pip/mypy-0.930
build(deps-dev): bump mypy from 0.920 to 0.930
2021-12-29 09:42:21 -07:00
Michael Hunhoff
cde4af40fe capa explorer: updating supported IDA versions 2021-12-28 10:51:53 -07:00
dependabot[bot]
a147755d13 build(deps-dev): bump mypy from 0.920 to 0.930
Bumps [mypy](https://github.com/python/mypy) from 0.920 to 0.930.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.920...v0.930)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-27 14:12:16 +00:00
dependabot[bot]
7b6c293069 build(deps): bump ruamel-yaml from 0.17.17 to 0.17.19
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.17 to 0.17.19.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-27 14:12:12 +00:00
dependabot[bot]
b3f1244641 build(deps-dev): bump types-psutil from 5.8.15 to 5.8.16
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.15 to 5.8.16.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-27 14:12:06 +00:00
Capa Bot
e6423700b9 Sync capa rules submodule 2021-12-23 16:34:46 +00:00
Moritz
9462a26a05 Merge pull request #844 from mandiant/dependabot/pip/mypy-0.920
build(deps-dev): bump mypy from 0.910 to 0.920
2021-12-20 16:31:41 +01:00
dependabot[bot]
c059a52d0e build(deps-dev): bump mypy from 0.910 to 0.920
Bumps [mypy](https://github.com/python/mypy) from 0.910 to 0.920.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.910...v0.920)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-20 14:09:06 +00:00
Capa Bot
a221db8a59 Sync capa rules submodule 2021-12-20 12:48:22 +00:00
Moritz
df43ed0219 Merge pull request #842 from mandiant/fix/maec-mal-fam
support maec/malware-family meta
2021-12-20 13:15:50 +01:00
Capa Bot
90430f52c6 Sync capa-testfiles submodule 2021-12-15 15:33:39 +00:00
Moritz Raabe
4e7f0b4591 support maec/malware-family meta 2021-12-15 10:40:34 +01:00
Capa Bot
bda76c22ec Sync capa rules submodule 2021-12-14 21:52:49 +00:00
Capa Bot
d67223c321 Sync capa rules submodule 2021-12-14 21:46:38 +00:00
Capa Bot
21278ff595 Sync capa rules submodule 2021-12-14 21:45:58 +00:00
Capa Bot
21fd6b27e2 Sync capa rules submodule 2021-12-13 18:48:16 +00:00
Capa Bot
cc8d57b242 Sync capa-testfiles submodule 2021-12-13 17:24:52 +00:00
Capa Bot
6081f4573c Sync capa-testfiles submodule 2021-12-13 17:24:32 +00:00
Capa Bot
ea2cafa715 Sync capa-testfiles submodule 2021-12-13 17:24:02 +00:00
Capa Bot
a34c993e31 Sync capa rules submodule 2021-12-07 04:32:49 +00:00
Willi Ballenthin
1a5fc3a21a Merge pull request #839 from cl3o/master
types: Add assert_never for exhaustivenes checking with mypy
2021-12-06 13:55:41 -07:00
cl3o
c15a9a72f5 Add local variable for easy_rules_by_feature at the beginning of match 2021-12-06 20:55:15 +01:00
cl3o
5b35058338 Forgot to add the second fix to the first commit. 2021-12-06 20:32:44 +01:00
cl3o
a0ca6e18c8 Made proposed changes to fix mypy errors 2021-12-06 20:30:07 +01:00
Capa Bot
1917004292 Sync capa rules submodule 2021-12-06 19:22:59 +00:00
Capa Bot
8ee3bb08bc Sync capa rules submodule 2021-12-06 18:24:54 +00:00
Capa Bot
7e96059fb5 Sync capa rules submodule 2021-12-06 17:58:59 +00:00
Capa Bot
4f7f06d316 Sync capa rules submodule 2021-12-06 17:57:11 +00:00
Capa Bot
448b5392be Sync capa rules submodule 2021-12-06 17:56:26 +00:00
Willi Ballenthin
6f5f3e091a Merge pull request #840 from mandiant/dependabot/pip/black-21.12b0
build(deps-dev): bump black from 21.11b1 to 21.12b0
2021-12-06 10:45:51 -07:00
dependabot[bot]
fa6a2069ce build(deps-dev): bump black from 21.11b1 to 21.12b0
Bumps [black](https://github.com/psf/black) from 21.11b1 to 21.12b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-06 14:12:23 +00:00
Capa Bot
09fd371b9d Sync capa-testfiles submodule 2021-12-06 10:13:41 +00:00
Capa Bot
a598745938 Sync capa-testfiles submodule 2021-12-06 10:06:57 +00:00
Capa Bot
7751f693c8 Sync capa-testfiles submodule 2021-12-06 10:02:45 +00:00
Capa Bot
7ade9ca43e Sync capa-testfiles submodule 2021-12-06 10:01:17 +00:00
cl3o
061a66e437 create function assert_never 2021-12-04 19:02:54 +01:00
Capa Bot
39536e2727 Sync capa rules submodule 2021-12-03 15:29:51 +00:00
Capa Bot
38038626d4 Sync capa rules submodule 2021-12-03 15:29:28 +00:00
Capa Bot
c3d34abe89 Sync capa-testfiles submodule 2021-12-03 12:12:30 +00:00
Capa Bot
baf5005998 Sync capa-testfiles submodule 2021-12-03 12:12:20 +00:00
Capa Bot
107c3c0cf9 Sync capa rules submodule 2021-11-30 22:06:21 +00:00
Capa Bot
2d1bd37816 Sync capa rules submodule 2021-11-30 15:24:28 +00:00
Capa Bot
de017b15d0 Sync capa-testfiles submodule 2021-11-30 15:24:09 +00:00
Capa Bot
3b0974ae3e Sync capa rules submodule 2021-11-29 23:46:52 +00:00
Willi Ballenthin
cf6cbc16df Merge pull request #838 from mandiant/dependabot/pip/types-psutil-5.8.15
build(deps-dev): bump types-psutil from 5.8.14 to 5.8.15
2021-11-29 08:47:44 -07:00
dependabot[bot]
bd60a8d9cd build(deps-dev): bump types-psutil from 5.8.14 to 5.8.15
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.14 to 5.8.15.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-29 14:09:09 +00:00
Capa Bot
c77240c6b4 Sync capa rules submodule 2021-11-26 16:21:34 +00:00
Moritz
14d803c604 Merge pull request #837 from mandiant/dependabot/pip/black-21.11b1
build(deps-dev): bump black from 21.10b0 to 21.11b1
2021-11-22 18:45:02 +01:00
dependabot[bot]
f764829ca9 build(deps-dev): bump black from 21.10b0 to 21.11b1
Bumps [black](https://github.com/psf/black) from 21.10b0 to 21.11b1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-22 14:10:19 +00:00
Willi Ballenthin
418eedd7bd freeze: fix doc describing format 2021-11-17 12:06:56 -07:00
Willi Ballenthin
b9f1fe56c8 Merge pull request #834 from mandiant/williballenthin-patch-1
setup: bump viv-utils to v0.6.9
2021-11-16 11:21:30 -07:00
Willi Ballenthin
7e50a957ff ci: tests: python versions are strings not floats 2021-11-16 10:12:34 -07:00
Willi Ballenthin
137cff6127 ci: tests: test under py3.10 too 2021-11-16 10:06:32 -07:00
Willi Ballenthin
807b99e5e5 changelog 2021-11-15 14:12:07 -07:00
Willi Ballenthin
e21c69f4e3 setup: bump viv-utils to v0.6.9
closes #816 
closes #683
2021-11-15 14:10:48 -07:00
Moritz
9f7daca86e Merge pull request #833 from mandiant/dependabot/pip/types-pyyaml-6.0.1
build(deps-dev): bump types-pyyaml from 6.0.0 to 6.0.1
2021-11-15 16:54:11 +01:00
Moritz
1b89e274c9 Merge pull request #832 from mandiant/dependabot/pip/isort-5.10.1
build(deps-dev): bump isort from 5.10.0 to 5.10.1
2021-11-15 16:54:02 +01:00
Moritz
dd768dc080 Merge pull request #831 from mandiant/dependabot/pip/viv-utils-flirt--0.6.8
build(deps): bump viv-utils[flirt] from 0.6.7 to 0.6.8
2021-11-15 16:53:53 +01:00
dependabot[bot]
4aea481967 build(deps-dev): bump types-pyyaml from 6.0.0 to 6.0.1
Bumps [types-pyyaml](https://github.com/python/typeshed) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-15 14:12:07 +00:00
dependabot[bot]
265629d127 build(deps-dev): bump isort from 5.10.0 to 5.10.1
Bumps [isort](https://github.com/pycqa/isort) from 5.10.0 to 5.10.1.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.10.0...5.10.1)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-15 14:12:04 +00:00
dependabot[bot]
cef0cb809f build(deps): bump viv-utils[flirt] from 0.6.7 to 0.6.8
Bumps [viv-utils[flirt]](https://github.com/williballenthin/viv-utils) from 0.6.7 to 0.6.8.
- [Release notes](https://github.com/williballenthin/viv-utils/releases)
- [Commits](https://github.com/williballenthin/viv-utils/compare/v0.6.7...v0.6.8)

---
updated-dependencies:
- dependency-name: viv-utils[flirt]
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-15 14:11:59 +00:00
Willi Ballenthin
57fe1e27b6 Merge pull request #830 from mandiant/perf/rule-selection
perf: don't try to match rules that will never match
2021-11-12 11:54:29 -07:00
Willi Ballenthin
83253eb7d0 rules: better variable name 2021-11-12 11:53:03 -07:00
Willi Ballenthin
9b5e8ff45d Update capa/rules.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2021-11-12 11:51:39 -07:00
William Ballenthin
cdfacc6247 Merge branch 'master' of github.com:fireeye/capa into perf/rule-selection 2021-11-10 14:30:08 -07:00
Capa Bot
10d747cc8c Sync capa rules submodule 2021-11-10 21:29:25 +00:00
William Ballenthin
a6b366602c mypy 2021-11-10 14:21:28 -07:00
William Ballenthin
80fb9dec3c pep8 2021-11-10 14:15:52 -07:00
William Ballenthin
68c86cf620 rules: easy/hard: better detect edge cases in optional, some, and range 2021-11-10 14:13:57 -07:00
William Ballenthin
e550d48bcd linter: optional maps to some, not range 2021-11-10 14:13:37 -07:00
William Ballenthin
1aaaa8919c rules: easy/hard: simplify indexing by considering not: hard 2021-11-10 13:55:34 -07:00
William Ballenthin
72c2ffc40b linter: add checks for not and optional not under and 2021-11-10 13:47:30 -07:00
William Ballenthin
f7ab2fb13a rules: easy/hard rules: detect not/optional at the root 2021-11-10 13:36:10 -07:00
William Ballenthin
3a1272246f rules: code consistency 2021-11-10 13:36:00 -07:00
William Ballenthin
6039a33bf8 engine: remove old import 2021-11-10 12:56:40 -07:00
William Ballenthin
2d68fb2536 pep8 2021-11-10 12:51:27 -07:00
William Ballenthin
845df282ef tests: split out match tests and validate alternative algorithms 2021-11-10 12:44:58 -07:00
William Ballenthin
1406dc28d9 rules: ruleset: fix collection of features under not statements 2021-11-10 12:44:19 -07:00
William Ballenthin
67884dd255 rules: match: more documentation 2021-11-09 16:42:32 -07:00
William Ballenthin
2bf05ac631 rules: index easy/hard: better handle not: statements 2021-11-09 16:37:30 -07:00
William Ballenthin
8cb04e4737 Merge branch 'master' into perf/rule-selection 2021-11-09 16:28:03 -07:00
William Ballenthin
733126591e Merge branch 'perf/query-optimizer' 2021-11-09 16:27:09 -07:00
William Ballenthin
d4d801c246 optimizer: tweak costs slightly 2021-11-09 16:26:26 -07:00
Willi Ballenthin
84ba32a8fe Merge pull request #829 from mandiant/perf/query-optimizer
perf: add query optimizer
2021-11-09 16:25:22 -07:00
William Ballenthin
ea386d02b6 tests: add test demonstrating optimizer 2021-11-09 16:24:26 -07:00
William Ballenthin
77cac63443 Merge branch 'master' into perf/query-optimizer 2021-11-09 16:12:30 -07:00
Willi Ballenthin
9350ee9479 Merge pull request #827 from mandiant/perf/short-circuit
perf: short circuit logic nodes when appropriate
2021-11-09 16:10:20 -07:00
Willi Ballenthin
025d156068 Merge pull request #828 from mandiant/profiling
profile infrastructure
2021-11-09 16:09:34 -07:00
William Ballenthin
7a4aee592b profile-time: add doc 2021-11-09 16:08:39 -07:00
Willi Ballenthin
f427c5e961 Update capa/engine.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2021-11-09 10:49:10 -07:00
Willi Ballenthin
51af2d4a56 Update capa/engine.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2021-11-09 10:49:01 -07:00
Willi Ballenthin
a68812b223 Update capa/engine.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2021-11-09 10:48:54 -07:00
William Ballenthin
e05f8c7034 changelog 2021-11-09 10:27:33 -07:00
William Ballenthin
182377581a main: use ruleset.match instead of engine.mathc 2021-11-09 09:52:45 -07:00
William Ballenthin
e647ae2ac4 rules: ruleset: add optimized match routine 2021-11-09 09:52:32 -07:00
William Ballenthin
1311da99ff rules: make Scope an enum 2021-11-09 09:51:50 -07:00
William Ballenthin
8badf226a2 engine: document match routine 2021-11-09 09:51:18 -07:00
William Ballenthin
6909d6a541 changelog 2021-11-08 16:04:15 -07:00
William Ballenthin
e287dc9a32 optimizer: fix sort order 2021-11-08 15:54:14 -07:00
William Ballenthin
152d0f3244 ruleset: add query optimizer 2021-11-08 15:34:59 -07:00
William Ballenthin
a6e2cfc90a Merge branch 'profiling' into perf/short-circuit 2021-11-08 15:24:50 -07:00
William Ballenthin
18c30e4f12 main: remove perf debug msgs 2021-11-08 15:24:43 -07:00
William Ballenthin
3c4f4d302c Merge branch 'profiling' into perf/short-circuit 2021-11-08 15:23:23 -07:00
William Ballenthin
2abebfbce7 main: remove perf messages 2021-11-08 15:22:58 -07:00
William Ballenthin
0b517c51d8 main: remove perf messages 2021-11-08 15:22:01 -07:00
William Ballenthin
9fbbda11b8 Merge branch 'profiling' into perf/short-circuit 2021-11-08 15:20:22 -07:00
William Ballenthin
6f6831f812 perf: document that counters is unstable 2021-11-08 15:20:11 -07:00
William Ballenthin
d425bb31c4 Merge branch 'profiling' into perf/short-circuit 2021-11-08 15:16:22 -07:00
William Ballenthin
334425a08f changelog 2021-11-08 15:16:08 -07:00
William Ballenthin
3e74da96a6 engine: make short circuiting configurable 2021-11-08 14:55:11 -07:00
William Ballenthin
ad119d789b Merge branch 'profiling' into perf/short-circuit 2021-11-08 14:35:26 -07:00
William Ballenthin
6c8d246af9 fix bad merge 2021-11-08 14:31:43 -07:00
William Ballenthin
26b7a0b91d Merge branch 'master' into profiling 2021-11-08 14:29:40 -07:00
Willi Ballenthin
0b6c6227b9 Merge pull request #825 from mandiant/fix/circular-import-freeze
fix circular import freeze
2021-11-08 14:28:01 -07:00
William Ballenthin
94fd7673fd common: mypy 2021-11-08 14:27:44 -07:00
William Ballenthin
f598acb8fc scripts: remove old profiling scripts 2021-11-08 14:24:48 -07:00
William Ballenthin
b621205a06 mypy 2021-11-08 14:24:13 -07:00
William Ballenthin
9fa9c6a5d0 tests: add test demonstrating short circuiting 2021-11-08 14:07:44 -07:00
William Ballenthin
1a84051679 changelog 2021-11-08 14:07:31 -07:00
William Ballenthin
d987719889 engine: some: correctly count satisfied children 2021-11-08 13:53:37 -07:00
William Ballenthin
96813c37b7 remove old improt 2021-11-08 13:48:33 -07:00
William Ballenthin
70f007525d pep8 2021-11-08 12:11:01 -07:00
William Ballenthin
e3496b0660 engine: move optimizer into its own module 2021-11-08 12:10:22 -07:00
William Ballenthin
24b4c99635 changelog 2021-11-08 11:58:02 -07:00
William Ballenthin
27b4a8ba73 common: remove old import 2021-11-08 11:55:58 -07:00
William Ballenthin
51b3f38f55 common: move Result to capa.common from capa.engine
fixes circular import error in capa.features.freeze
2021-11-08 11:54:36 -07:00
William Ballenthin
a35be4a666 scripts: add py script for profiling time 2021-11-08 11:52:34 -07:00
William Ballenthin
5770d0c12d perf: add reset routine 2021-11-08 11:52:25 -07:00
William Ballenthin
0629c584e1 common: move Result to capa.common from capa.engine
fixes circular import error in capa.features.freeze
2021-11-08 11:52:13 -07:00
William Ballenthin
480df323e5 scripts: add py script for profiling time 2021-11-08 11:51:09 -07:00
William Ballenthin
a995b53c38 perf: add reset routine 2021-11-08 11:50:49 -07:00
William Ballenthin
35fa50dbee pep8 2021-11-08 11:50:37 -07:00
William Ballenthin
d86c3f4d48 common: move Result to capa.common from capa.engine
fixes circular import error in capa.features.freeze
2021-11-08 11:50:16 -07:00
Moritz
4696c0ebb6 Merge pull request #822 from mandiant/dependabot/pip/types-psutil-5.8.14
build(deps-dev): bump types-psutil from 5.8.13 to 5.8.14
2021-11-08 17:02:58 +01:00
Moritz
09724e9787 Merge pull request #823 from mandiant/dependabot/pip/isort-5.10.0
build(deps-dev): bump isort from 5.9.3 to 5.10.0
2021-11-08 17:02:33 +01:00
dependabot[bot]
636548cdec build(deps-dev): bump isort from 5.9.3 to 5.10.0
Bumps [isort](https://github.com/pycqa/isort) from 5.9.3 to 5.10.0.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.9.3...5.10.0)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-08 14:16:28 +00:00
dependabot[bot]
b3970808df build(deps-dev): bump types-psutil from 5.8.13 to 5.8.14
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.13 to 5.8.14.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-08 14:16:15 +00:00
William Ballenthin
d573b83c94 rule: optimization: add some documentation 2021-11-05 16:49:38 -06:00
William Ballenthin
e63f072e40 rules: optimizer: use recursive cost of statements 2021-11-05 16:39:00 -06:00
William Ballenthin
a329147d28 engine: some: short circuit 2021-11-05 16:32:23 -06:00
William Ballenthin
18ba986eba engine: or: short circuit 2021-11-05 16:32:12 -06:00
William Ballenthin
8d9f418b2b rules: optimize by cost 2021-11-05 16:20:22 -06:00
William Ballenthin
623bac1a40 engine: statement: document that the order of children is important 2021-11-05 16:19:16 -06:00
William Ballenthin
702d00da91 gitignore 2021-11-05 15:24:24 -06:00
William Ballenthin
3a12472be8 perf: render: show evaluate.feature counter 2021-11-05 15:23:34 -06:00
William Ballenthin
6524449ad1 main: perf: human format the numbers 2021-11-05 15:23:22 -06:00
William Ballenthin
86cab26a69 add perf counters in module capa.perf 2021-11-05 14:59:22 -06:00
William Ballenthin
3d068fe3cd scripts: add utilities for collecting profile traces 2021-11-04 13:17:38 -06:00
William Ballenthin
f98236046b main: add coarse timing measurements 2021-11-04 12:38:35 -06:00
William Ballenthin
ed3bd4ef75 main: add timing ctx manager 2021-11-04 12:20:05 -06:00
Capa Bot
7d3ae7a91b Sync capa rules submodule 2021-11-03 18:29:09 +00:00
Capa Bot
0409c431b8 Sync capa rules submodule 2021-11-02 18:47:47 +00:00
Capa Bot
ffbb841b03 Sync capa rules submodule 2021-11-02 18:47:18 +00:00
Willi Ballenthin
e9a7dbc2ff Merge pull request #820 from mandiant/fix/linter-file-format
auto recognize shellcode based on file extension
2021-11-02 11:31:33 -06:00
Capa Bot
10dc8950c1 Sync capa rules submodule 2021-11-02 17:29:30 +00:00
Capa Bot
fe0fb1ccd2 Sync capa rules submodule 2021-11-02 17:17:47 +00:00
Moritz Raabe
e9170a1d4b auto recognize shellcode based on file extension 2021-11-02 18:02:37 +01:00
Capa Bot
02bd8581d8 Sync capa-testfiles submodule 2021-11-02 16:42:40 +00:00
Moritz
ca574201a4 Merge pull request #818 from mandiant/dependabot/pip/ruamel-yaml-0.17.17
build(deps): bump ruamel-yaml from 0.17.16 to 0.17.17
2021-11-02 17:36:03 +01:00
Moritz
8e744d94e6 Merge pull request #817 from mandiant/dependabot/pip/black-21.10b0
build(deps-dev): bump black from 21.9b0 to 21.10b0
2021-11-02 17:35:52 +01:00
dependabot[bot]
6a28330dd1 build(deps): bump ruamel-yaml from 0.17.16 to 0.17.17
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.16 to 0.17.17.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 14:11:49 +00:00
dependabot[bot]
4537b52c18 build(deps-dev): bump black from 21.9b0 to 21.10b0
Bumps [black](https://github.com/psf/black) from 21.9b0 to 21.10b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 14:11:42 +00:00
Willi Ballenthin
29e61e24a6 Merge pull request #815 from mandiant/feature-3.0.3
v3.0.3
2021-10-27 10:14:35 -06:00
William Ballenthin
041c8a4c2d changelog 2021-10-27 09:43:35 -06:00
Capa Bot
433dfd8fa9 Sync capa rules submodule 2021-10-27 15:34:46 +00:00
William Ballenthin
2b46043419 v3.0.3 2021-10-27 09:32:45 -06:00
William Ballenthin
d31c8b0190 changelog 2021-10-27 09:29:54 -06:00
Willi Ballenthin
9003fdc1a2 Merge pull request #814 from mandiant/fix-802
bail with unique error codes
2021-10-27 09:25:55 -06:00
William Ballenthin
b1f4a2853e Merge branch 'master' of github.com:fireeye/capa into fix-802 2021-10-27 09:25:29 -06:00
William Ballenthin
07412f047d tests: fix check of status code E_MISSING_FILE 2021-10-27 09:24:22 -06:00
Willi Ballenthin
26ac21b908 Merge pull request #813 from mandiant/fix-130
Fix 130
2021-10-27 09:20:43 -06:00
William Ballenthin
4cc496a8e5 main: use constants to represent error codes 2021-10-26 16:57:33 -06:00
William Ballenthin
4f4e0881b5 changelog 2021-10-26 16:48:02 -06:00
William Ballenthin
9fe164665c main: exit with unique error codes when bailing
TODO: create an enum of all these things so they're easy for a human to
read.

closes #802
2021-10-26 16:46:43 -06:00
William Ballenthin
c74193b5d7 Merge branch 'master' of github.com:fireeye/capa into fix-130 2021-10-26 15:26:22 -06:00
William Ballenthin
31ef06ef2b sync testfiles 2021-10-26 15:26:18 -06:00
Capa Bot
83a95d66d1 Sync capa-testfiles submodule 2021-10-26 21:24:10 +00:00
William Ballenthin
4451b76f89 pep8 2021-10-26 15:21:28 -06:00
William Ballenthin
a1075b63ec tests: add demonstration of bb layout 2021-10-26 15:20:08 -06:00
William Ballenthin
97c41228e0 changelog 2021-10-26 15:10:50 -06:00
William Ballenthin
8903d2abcb show-capabilities-by-function: also include matches from BBs in fn 2021-10-26 15:05:53 -06:00
William Ballenthin
328e13fbfe main: compute function & bb layout
so bb can be associated with function in output.
only captures BBs that have a rule match,
otherwise, there might be too much data captured.
closes #130.
2021-10-26 15:04:50 -06:00
Capa Bot
b7cd5fec76 Sync capa rules submodule 2021-10-25 19:26:56 +00:00
Willi Ballenthin
6086dbcd84 Merge pull request #812 from mandiant/dependabot/pip/viv-utils-flirt--0.6.7
build(deps): bump viv-utils[flirt] from 0.6.6 to 0.6.7
2021-10-25 09:14:41 -06:00
Willi Ballenthin
5f88e02aa3 Merge pull request #811 from mandiant/dependabot/pip/types-pyyaml-6.0.0
build(deps-dev): bump types-pyyaml from 5.4.12 to 6.0.0
2021-10-25 09:04:56 -06:00
dependabot[bot]
96a4f585cd build(deps): bump viv-utils[flirt] from 0.6.6 to 0.6.7
Bumps [viv-utils[flirt]](https://github.com/williballenthin/viv-utils) from 0.6.6 to 0.6.7.
- [Release notes](https://github.com/williballenthin/viv-utils/releases)
- [Commits](https://github.com/williballenthin/viv-utils/compare/v0.6.6...v0.6.7)

---
updated-dependencies:
- dependency-name: viv-utils[flirt]
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-25 14:09:33 +00:00
dependabot[bot]
73ec980e01 build(deps-dev): bump types-pyyaml from 5.4.12 to 6.0.0
Bumps [types-pyyaml](https://github.com/python/typeshed) from 5.4.12 to 6.0.0.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-25 14:09:26 +00:00
Capa Bot
e5ed7ce0d3 Sync capa rules submodule 2021-10-25 03:39:00 +00:00
Capa Bot
08a7b8afb7 Sync capa-testfiles submodule 2021-10-24 22:00:33 +00:00
Capa Bot
bb7a588f6b Sync capa rules submodule 2021-10-22 17:23:31 +00:00
Capa Bot
9faa0734c1 Sync capa-testfiles submodule 2021-10-22 17:11:32 +00:00
Capa Bot
cf55b34b4e Sync capa-testfiles submodule 2021-10-22 16:57:10 +00:00
Capa Bot
5881899cc2 Sync capa-testfiles submodule 2021-10-22 16:56:36 +00:00
William Ballenthin
4e64ef8ab3 gitignore 2021-10-22 10:20:14 -06:00
Willi Ballenthin
7e5532ac84 Merge pull request #807 from mandiant/dependabot/pip/types-pyyaml-5.4.12
build(deps-dev): bump types-pyyaml from 5.4.10 to 5.4.12
2021-10-18 13:49:55 -06:00
dependabot[bot]
3d638df08c build(deps-dev): bump types-pyyaml from 5.4.10 to 5.4.12
Bumps [types-pyyaml](https://github.com/python/typeshed) from 5.4.10 to 5.4.12.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-18 18:50:32 +00:00
Willi Ballenthin
bf984a38ed Merge pull request #808 from mandiant/dependabot/pip/types-tabulate-0.8.3
build(deps-dev): bump types-tabulate from 0.8.2 to 0.8.3
2021-10-18 12:49:47 -06:00
dependabot[bot]
e68f2ce141 build(deps-dev): bump types-tabulate from 0.8.2 to 0.8.3
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.2 to 0.8.3.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-18 18:42:21 +00:00
Willi Ballenthin
d0a3244108 Merge pull request #809 from mandiant/dependabot/pip/types-termcolor-1.1.2
build(deps-dev): bump types-termcolor from 1.1.1 to 1.1.2
2021-10-18 12:41:37 -06:00
dependabot[bot]
d09901d512 build(deps-dev): bump types-termcolor from 1.1.1 to 1.1.2
Bumps [types-termcolor](https://github.com/python/typeshed) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-termcolor
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-18 18:26:20 +00:00
Willi Ballenthin
2d46bac351 Merge pull request #810 from mandiant/dependabot/pip/types-psutil-5.8.13
build(deps-dev): bump types-psutil from 5.8.12 to 5.8.13
2021-10-18 12:25:22 -06:00
Willi Ballenthin
2285c76cbf Merge pull request #806 from mandiant/dependabot/pip/types-colorama-0.4.4
build(deps-dev): bump types-colorama from 0.4.3 to 0.4.4
2021-10-18 12:25:08 -06:00
dependabot[bot]
c003ab4e42 build(deps-dev): bump types-psutil from 5.8.12 to 5.8.13
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.12 to 5.8.13.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-18 18:24:52 +00:00
Willi Ballenthin
78e97a217a Merge pull request #805 from mandiant/dependabot/pip/pyyaml-6.0
build(deps): bump pyyaml from 5.4.1 to 6.0
2021-10-18 12:24:20 -06:00
dependabot[bot]
720585170c build(deps-dev): bump types-colorama from 0.4.3 to 0.4.4
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.3 to 0.4.4.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-18 14:15:08 +00:00
dependabot[bot]
19d54f3f4d build(deps): bump pyyaml from 5.4.1 to 6.0
Bumps [pyyaml](https://github.com/yaml/pyyaml) from 5.4.1 to 6.0.
- [Release notes](https://github.com/yaml/pyyaml/releases)
- [Changelog](https://github.com/yaml/pyyaml/blob/master/CHANGES)
- [Commits](https://github.com/yaml/pyyaml/compare/5.4.1...6.0)

---
updated-dependencies:
- dependency-name: pyyaml
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-18 14:15:05 +00:00
Moritz
23a0aec1e6 Merge pull request #803 from mandiant/dependabot/pip/types-psutil-5.8.12
build(deps-dev): bump types-psutil from 5.8.8 to 5.8.12
2021-10-12 14:22:52 +02:00
Moritz
6b0db01c13 Merge pull request #804 from mandiant/dependabot/pip/pycodestyle-2.8.0
build(deps-dev): bump pycodestyle from 2.7.0 to 2.8.0
2021-10-12 14:22:44 +02:00
dependabot[bot]
93c14c3a1f build(deps-dev): bump pycodestyle from 2.7.0 to 2.8.0
Bumps [pycodestyle](https://github.com/PyCQA/pycodestyle) from 2.7.0 to 2.8.0.
- [Release notes](https://github.com/PyCQA/pycodestyle/releases)
- [Changelog](https://github.com/PyCQA/pycodestyle/blob/main/CHANGES.txt)
- [Commits](https://github.com/PyCQA/pycodestyle/compare/2.7.0...2.8.0)

---
updated-dependencies:
- dependency-name: pycodestyle
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-11 14:10:44 +00:00
dependabot[bot]
b66760fc5c build(deps-dev): bump types-psutil from 5.8.8 to 5.8.12
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.8 to 5.8.12.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-11 14:10:38 +00:00
Willi Ballenthin
64a801cc55 Merge pull request #801 from mandiant/dependabot/pip/pytest-cov-3.0.0
build(deps-dev): bump pytest-cov from 2.12.1 to 3.0.0
2021-10-04 14:13:43 -06:00
dependabot[bot]
35fc8ee3e8 build(deps-dev): bump pytest-cov from 2.12.1 to 3.0.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.12.1 to 3.0.0.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.12.1...v3.0.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-04 14:09:30 +00:00
Capa Bot
887c566f7c Sync capa rules submodule 2021-09-30 19:28:13 +00:00
Capa Bot
2f59499087 Sync capa rules submodule 2021-09-30 14:01:54 +00:00
Capa Bot
b4a239569c Sync capa rules submodule 2021-09-30 13:29:23 +00:00
Moritz
e4073a844b Merge pull request #794 from mandiant/go-mandiant
s/fireeye/mandiant
2021-09-30 15:28:53 +02:00
Capa Bot
f313ad37b3 Sync capa-testfiles submodule 2021-09-29 14:54:48 +00:00
Moritz Raabe
8de69c639a s/fireeye/mandiant 2021-09-29 12:55:16 +02:00
Willi Ballenthin
0714dbee0d changelog: formatting 2021-09-28 10:26:28 -06:00
Willi Ballenthin
ead8a836be Merge pull request #799 from mandiant/williballenthin-patch-1
v3.0.2
2021-09-28 10:25:10 -06:00
Willi Ballenthin
d471e66073 v3.0.2 2021-09-28 09:44:46 -06:00
Willi Ballenthin
4ddef1f60b changelog: v3.0.2 2021-09-28 09:41:12 -06:00
Moritz
7b9da896e8 Merge pull request #797 from mandiant/fix/pyinstaller-elf
PyInstaller fix: add hidden import and test
2021-09-28 17:37:36 +02:00
Moritz Raabe
41786f4ab8 add hidden import and test 2021-09-28 15:39:23 +02:00
Capa Bot
4661da729f Sync capa-testfiles submodule 2021-09-28 10:15:01 +00:00
Capa Bot
97dc40a585 Sync capa-testfiles submodule 2021-09-28 10:04:34 +00:00
Moritz
f2082f3f52 release v3.0.1 (#791)
* release v3.0.1

* Update CHANGELOG.md

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2021-09-27 20:59:18 +02:00
Moritz
f87c8ced3f Merge pull request #792 from mandiant/dependabot/pip/types-psutil-5.8.8
build(deps-dev): bump types-psutil from 5.8.5 to 5.8.8
2021-09-27 16:54:49 +02:00
dependabot[bot]
f914eea8ae build(deps-dev): bump types-psutil from 5.8.5 to 5.8.8
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.5 to 5.8.8.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-27 14:18:14 +00:00
Willi Ballenthin
b41d239301 Merge pull request #790 from mandiant/refactor/viv-utils-flirt
use viv-utils functions
2021-09-23 14:29:30 -06:00
Moritz Raabe
8bb1a1cb5a use viv-utils functions 2021-09-23 19:35:14 +02:00
Willi Ballenthin
2f61bc0b05 Merge pull request #789 from mandiant/dependabot/pip/tqdm-4.62.3
build(deps): bump tqdm from 4.62.2 to 4.62.3
2021-09-23 08:26:59 -06:00
dependabot[bot]
d22557947a build(deps): bump tqdm from 4.62.2 to 4.62.3
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.62.2 to 4.62.3.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.62.2...v4.62.3)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-23 14:24:28 +00:00
Moritz
3e44d07541 Merge pull request #786 from fireeye/williballenthin-patch-1
setup.py: bump viv dep to v1.0.5
2021-09-23 10:21:20 +02:00
Willi Ballenthin
f56b27e1c7 changelog 2021-09-22 21:39:36 -06:00
Willi Ballenthin
12075df3ba setup.py: bump viv dep to v1.0.5 2021-09-22 21:34:17 -06:00
Moritz
a8bb9620e2 Merge pull request #785 from fireeye/dependabot/pip/black-21.9b0
build(deps-dev): bump black from 21.8b0 to 21.9b0
2021-09-20 19:03:35 +02:00
dependabot[bot]
9ed4e21429 build(deps-dev): bump black from 21.8b0 to 21.9b0
Bumps [black](https://github.com/psf/black) from 21.8b0 to 21.9b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-20 14:02:13 +00:00
Capa Bot
5b293d675f Sync capa-testfiles submodule 2021-09-15 21:40:34 +00:00
Willi Ballenthin
5972d6576d Merge pull request #776 from fireeye/fix-775
v3.0.0
2021-09-14 21:37:37 -06:00
William Ballenthin
19ce514b5c main: handle malformed ELF files
closes #777
2021-09-14 21:35:47 -06:00
William Ballenthin
144ed80c56 readme: add reference to third blog post 2021-09-14 21:14:44 -06:00
William Ballenthin
4d34e56589 changelog: wording 2021-09-14 21:12:46 -06:00
William Ballenthin
9045770192 version: v3.0 2021-09-14 21:09:58 -06:00
William Ballenthin
4ea21d2a9c changelog: v3.0 2021-09-14 21:08:58 -06:00
Moritz
774a188d19 Merge pull request #774 from fireeye/no-flirt-elf
disable flirt matching on elf files
2021-09-14 18:59:20 +02:00
Capa Bot
bd5c125561 Sync capa rules submodule 2021-09-14 15:29:28 +00:00
Moritz
420feea0aa Update capa/main.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2021-09-14 17:27:40 +02:00
Capa Bot
b298f547f9 Sync capa rules submodule 2021-09-14 15:26:51 +00:00
Capa Bot
a7fe76c336 Sync capa rules submodule 2021-09-14 15:25:46 +00:00
Willi Ballenthin
9f777ba152 readme: reference ELF support 2021-09-14 09:22:33 -06:00
Moritz Raabe
cc3b56ddcb disable flirt matching on elf files 2021-09-14 13:59:38 +02:00
Moritz Raabe
0c42942a88 black code style 2021-09-14 09:57:33 +02:00
William Ballenthin
0803c6f3fa elffile: extract global features 2021-09-13 13:51:19 -06:00
William Ballenthin
02d9d37c1e *: raise NotImplementedError not NotImplemented
> NotImplementedError and NotImplemented are not interchangeable, even though they have similar names and purposes. See NotImplemented for details on when to use it.

https://docs.python.org/3/library/exceptions.html#NotImplementedError
2021-09-13 13:47:30 -06:00
William Ballenthin
c121e9219c elffile: fix mypy 2021-09-13 13:32:09 -06:00
Willi Ballenthin
297d9aaa32 Merge pull request #770 from fireeye/elffile-extractor
add light weight ElfFeatureExtractor
2021-09-13 13:27:00 -06:00
Willi Ballenthin
11644cbc31 Update capa/features/extractors/elffile.py 2021-09-13 13:20:52 -06:00
Moritz Raabe
4c6be15edc minor fixes 2021-09-13 21:15:31 +02:00
Willi Ballenthin
e1028e4dd8 Merge pull request #773 from fireeye/dependabot/pip/types-psutil-5.8.5
build(deps-dev): bump types-psutil from 5.8.2 to 5.8.5
2021-09-13 09:29:20 -06:00
dependabot[bot]
861ff1c91f build(deps-dev): bump types-psutil from 5.8.2 to 5.8.5
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.2 to 5.8.5.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-13 14:03:31 +00:00
Moritz Raabe
80bb0b4aff init variable :/ 2021-09-10 21:29:59 +02:00
Moritz Raabe
06d238a9f9 add ElfFeatureExtractor 2021-09-10 20:38:27 +02:00
mike-hunhoff
71ce28d9e6 Merge pull request #768 from fireeye/explorer/fix/745
explorer: improve parsing algorithm for rule generator feature editor
2021-09-10 10:37:52 -06:00
Moritz
c48429e5c3 Merge pull request #766 from fireeye/ci/update-ubuntu-16
update to ubuntu-18.04
2021-09-10 10:28:31 +02:00
Willi Ballenthin
34e3f7bbaf Merge pull request #759 from fireeye/fix-755
extractors: extract global features as their own pseudo scope
2021-09-09 20:16:48 -06:00
Michael Hunhoff
db624460bc explorer: improve parsing algorithm for rule generator feature editor 2021-09-09 15:45:04 -06:00
Moritz Raabe
16c12f816b update to ubuntu-18.04 2021-09-09 16:45:11 +02:00
Capa Bot
ea6fed56a2 Sync capa rules submodule 2021-09-08 14:41:58 +00:00
Moritz
22f11f1a97 Merge pull request #763 from fireeye/dependabot/pip/types-psutil-5.8.2
build(deps-dev): bump types-psutil from 5.8.0 to 5.8.2
2021-09-06 23:03:20 +02:00
Moritz
7c21ccb8f9 Merge pull request #762 from fireeye/dependabot/pip/types-pyyaml-5.4.10
build(deps-dev): bump types-pyyaml from 5.4.8 to 5.4.10
2021-09-06 23:03:11 +02:00
Moritz
8f86b0eac2 Merge pull request #761 from fireeye/dependabot/pip/pytest-6.2.5
build(deps-dev): bump pytest from 6.2.4 to 6.2.5
2021-09-06 23:03:02 +02:00
Moritz
9c8fa32e5c Merge pull request #760 from fireeye/dependabot/pip/pefile-2021.9.3
build(deps): bump pefile from 2021.5.24 to 2021.9.3
2021-09-06 23:02:54 +02:00
dependabot[bot]
9d348c6da2 build(deps-dev): bump types-psutil from 5.8.0 to 5.8.2
Bumps [types-psutil](https://github.com/python/typeshed) from 5.8.0 to 5.8.2.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-psutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-06 14:02:56 +00:00
dependabot[bot]
4dc87240f9 build(deps-dev): bump types-pyyaml from 5.4.8 to 5.4.10
Bumps [types-pyyaml](https://github.com/python/typeshed) from 5.4.8 to 5.4.10.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-06 14:02:54 +00:00
dependabot[bot]
a60d11a763 build(deps-dev): bump pytest from 6.2.4 to 6.2.5
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.4 to 6.2.5.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.4...6.2.5)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-06 14:02:52 +00:00
dependabot[bot]
391cc77996 build(deps): bump pefile from 2021.5.24 to 2021.9.3
Bumps [pefile](https://github.com/erocarrera/pefile) from 2021.5.24 to 2021.9.3.
- [Release notes](https://github.com/erocarrera/pefile/releases)
- [Commits](https://github.com/erocarrera/pefile/compare/v2021.5.24...v2021.9.3)

---
updated-dependencies:
- dependency-name: pefile
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-06 14:02:48 +00:00
William Ballenthin
7a3287fa25 extractors: smda: fix missing yield from 2021-09-04 16:55:37 -06:00
William Ballenthin
32244b2641 fixtures: fix extraction of global features 2021-09-04 16:12:51 -06:00
William Ballenthin
122fdc69e3 fixtures: name error 2021-09-04 16:00:49 -06:00
William Ballenthin
39e4e47763 pep8 2021-09-04 15:59:38 -06:00
William Ballenthin
2ea4dc9d7e tests: fixtures: extract global features at each scope 2021-09-04 15:58:32 -06:00
William Ballenthin
b2590e7c9a changelog 2021-09-04 15:55:28 -06:00
William Ballenthin
af6fe6baa0 extractors: extract global features as their own pseudo scope
this means they can be extracted separately in the freeze format.

closes #755
2021-09-04 15:53:05 -06:00
Moritz
ce799dadbe Merge pull request #758 from fireeye/explorer/new-feature-support
adding support for arch, os, and format features
2021-09-02 20:39:08 +02:00
Michael Hunhoff
217e6f88d9 adding support for arch, os, and format features 2021-09-02 08:29:55 -06:00
Moritz
a363baffce Merge pull request #757 from davidt99/master
fix: use netwrokx import since nx is deprecated
2021-08-31 11:02:40 +02:00
Capa Bot
bbe47d81e9 Sync capa rules submodule 2021-08-30 16:30:52 +00:00
davidt99
a105b41647 fix: use netwrokx import since nx is deprecated 2021-08-30 19:11:30 +03:00
Capa Bot
fc8919adce Sync capa-testfiles submodule 2021-08-30 15:51:01 +00:00
Willi Ballenthin
f21877ae27 Merge pull request #750 from fireeye/dependabot/pip/types-pyyaml-5.4.8
build(deps-dev): bump types-pyyaml from 5.4.6 to 5.4.8
2021-08-30 08:46:01 -06:00
Willi Ballenthin
99e7967e22 Merge pull request #752 from fireeye/dependabot/pip/ruamel-yaml-0.17.16
build(deps): bump ruamel-yaml from 0.17.13 to 0.17.16
2021-08-30 08:45:47 -06:00
Willi Ballenthin
766fe9d845 Merge pull request #754 from fireeye/dependabot/pip/black-21.8b0
build(deps-dev): bump black from 21.7b0 to 21.8b0
2021-08-30 08:44:40 -06:00
dependabot[bot]
2c60faee26 build(deps-dev): bump black from 21.7b0 to 21.8b0
Bumps [black](https://github.com/psf/black) from 21.7b0 to 21.8b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-30 14:02:09 +00:00
dependabot[bot]
097f1d4695 build(deps): bump ruamel-yaml from 0.17.13 to 0.17.16
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.13 to 0.17.16.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-30 14:02:03 +00:00
dependabot[bot]
a6efc3952f build(deps-dev): bump types-pyyaml from 5.4.6 to 5.4.8
Bumps [types-pyyaml](https://github.com/python/typeshed) from 5.4.6 to 5.4.8.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-30 14:01:55 +00:00
Moritz
dadd76bd62 Merge pull request #747 from fireeye/feature-linter-pbar
linter enhancements
2021-08-30 12:18:19 +02:00
William Ballenthin
282c0c2655 lint: guide mypy typing to address CI issues 2021-08-27 13:00:40 -06:00
William Ballenthin
14f2391f49 mypy: add devtools ignore 2021-08-27 12:33:04 -06:00
William Ballenthin
b5860190e3 linter: invoke gc 2021-08-27 09:47:34 -06:00
William Ballenthin
d8ecb88867 changelog 2021-08-27 09:37:53 -06:00
William Ballenthin
f5b2efdc87 lint: reduce logging verbosity 2021-08-27 09:36:32 -06:00
William Ballenthin
fab26180cb lint: cache analysis results per path 2021-08-27 09:24:36 -06:00
William Ballenthin
3968d40bf4 linter: use pathlib.Path 2021-08-27 09:11:28 -06:00
William Ballenthin
cb2d1cde36 linter: add typing 2021-08-27 09:04:37 -06:00
William Ballenthin
da7a9b7232 linter: don't show noisey "need example" warnings in nursery 2021-08-27 08:42:46 -06:00
William Ballenthin
4f15225665 lint: handle calls to print within pbar 2021-08-27 08:34:02 -06:00
William Ballenthin
90708c123b linter: show progress bar 2021-08-27 08:21:09 -06:00
Capa Bot
384f467d4a Sync capa rules submodule 2021-08-26 23:53:30 +00:00
Capa Bot
37064f20d1 Sync capa rules submodule 2021-08-26 23:49:07 +00:00
Willi Ballenthin
9e579f9de3 tests: viv: reenable elf tests
revert 56f9e16a8b

viv is reverted to v1.0.3 so tests should pass again ref $735
2021-08-26 16:50:57 -06:00
Willi Ballenthin
b2c688ef14 Merge pull request #746 from fireeye/revert-731-dependabot/pip/vivisect-1.0.4
Revert "build(deps): bump vivisect from 1.0.3 to 1.0.4"
2021-08-26 13:00:13 -06:00
Willi Ballenthin
9717acd988 Revert "build(deps): bump vivisect from 1.0.3 to 1.0.4" 2021-08-26 12:59:49 -06:00
mike-hunhoff
d06c5b12c2 Merge pull request #742 from fireeye/fix/740
explorer: small performance boost to rule generator search functionality
2021-08-26 10:35:20 -06:00
Capa Bot
e97a120602 Sync capa rules submodule 2021-08-26 15:12:41 +00:00
Capa Bot
5b806b08dd Sync capa rules submodule 2021-08-26 15:12:14 +00:00
Willi Ballenthin
fd5dfcc6d8 Merge pull request #743 from fireeye/feature-lint-ntoskrnl-ntdll-exceptions
fix linter ntoskrnl/ntdll exceptions
2021-08-26 08:56:45 -06:00
Michael Hunhoff
3979317b10 merging upstream 2021-08-26 08:26:41 -06:00
mike-hunhoff
8d2595a6db Update README.md 2021-08-26 08:20:38 -06:00
mike-hunhoff
3c2c452501 Merge pull request #741 from fireeye/doc/explorer-support
explorer: updating support documentation and runtime checks
2021-08-26 08:19:01 -06:00
Michael Hunhoff
af48f86e55 Merge branch 'doc/explorer-support' of github.com:fireeye/capa into doc/explorer-support 2021-08-26 08:16:25 -06:00
Michael Hunhoff
73957ea14e merging upstream 2021-08-26 08:15:25 -06:00
William Ballenthin
bb824e9167 Merge branch 'master' into feature-lint-ntoskrnl-ntdll-exceptions 2021-08-25 16:44:29 -06:00
William Ballenthin
b996e77606 setup: add psutil deps to [dev] 2021-08-25 16:43:46 -06:00
William Ballenthin
9a20bbd4e1 changelog 2021-08-25 16:39:57 -06:00
William Ballenthin
8195b7565f lint: hardcoded some exports of ntdll/ntoskrnl to reduce warning spam 2021-08-25 16:36:36 -06:00
William Ballenthin
0569f9b242 lint: show mod/imp names per rule
fix bug where the same mod/imp name pair was shown for all rules
2021-08-25 16:36:08 -06:00
Michael Hunhoff
8ffa8ea2c8 explorer: small performance boost to rule generator search functionality 2021-08-25 15:45:47 -06:00
Capa Bot
fd7cff6109 Sync capa rules submodule 2021-08-25 20:34:00 +00:00
mike-hunhoff
a3b292066a Update capa/ida/helpers.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2021-08-25 13:03:45 -06:00
Michael Hunhoff
8f6d38468e explorer: updating support documentation and runtime checks 2021-08-25 12:46:34 -06:00
William Ballenthin
4af5cc66ba changelog 2021-08-24 17:53:56 -06:00
William Ballenthin
33c3c7e106 scripts: profile-memory: show vms, too 2021-08-24 17:26:45 -06:00
William Ballenthin
5c75f12b78 scripts: profile-memory: show incremental duration and RSS 2021-08-24 17:22:18 -06:00
William Ballenthin
1ae6638861 Merge branch 'master' of github.com:fireeye/capa 2021-08-24 17:05:59 -06:00
William Ballenthin
d8999471c5 scripts: add profile-memory
ref #736
2021-08-24 17:05:34 -06:00
Capa Bot
90c0de1a7f Sync capa rules submodule 2021-08-24 22:48:07 +00:00
Capa Bot
d13ea1cbbe Sync capa rules submodule 2021-08-24 22:34:04 +00:00
Willi Ballenthin
03cf28fccd Merge pull request #739 from fireeye/feature-737
rules: add substring feature
2021-08-24 16:33:17 -06:00
William Ballenthin
8e757d2099 show-features: print function addresses, too 2021-08-24 16:32:44 -06:00
William Ballenthin
2989732637 tests: fix fva of substring test function 2021-08-24 16:32:27 -06:00
William Ballenthin
db45068357 tests: fix tests for substring 2021-08-24 16:13:41 -06:00
Capa Bot
735aea86e0 Sync capa rules submodule 2021-08-24 18:41:34 +00:00
William Ballenthin
d8c8c6d2f3 lint: apply string lints to substrings, too 2021-08-24 11:52:28 -06:00
William Ballenthin
3b4cb47597 pep8 2021-08-24 11:45:48 -06:00
William Ballenthin
f55e758d47 tests: rules: demonstrate substring with description 2021-08-24 11:45:24 -06:00
William Ballenthin
c5a5e5600a changelog: substring 2021-08-24 11:37:07 -06:00
William Ballenthin
6989e8b8cf rules: add substring feature
closes #737
2021-08-24 11:35:01 -06:00
Capa Bot
7d2e550b84 Sync capa rules submodule 2021-08-24 16:35:30 +00:00
Capa Bot
7f17c45b69 Sync capa rules submodule 2021-08-24 16:06:15 +00:00
Willi Ballenthin
b0c86ab8db Merge pull request #738 from fireeye/revert-697-dependabot/pip/networkx-2.6.2
Revert "build(deps): bump networkx from 2.5.1 to 2.6.2"
2021-08-24 09:50:49 -06:00
Willi Ballenthin
4c0c2c75c6 Revert "build(deps): bump networkx from 2.5.1 to 2.6.2" 2021-08-24 09:50:39 -06:00
Capa Bot
1549b9b506 Sync capa rules submodule 2021-08-24 15:47:44 +00:00
Capa Bot
057eeb3629 Sync capa-testfiles submodule 2021-08-24 15:45:39 +00:00
Capa Bot
0dea4e8b7d Sync capa-testfiles submodule 2021-08-24 15:45:04 +00:00
Willi Ballenthin
d3573a565c Merge pull request #723 from fireeye/feature-701
os, arch, and format features
2021-08-24 08:56:29 -06:00
Willi Ballenthin
1275b49ebb Merge pull request #697 from fireeye/dependabot/pip/networkx-2.6.2
build(deps): bump networkx from 2.5.1 to 2.6.2
2021-08-24 08:56:17 -06:00
William Ballenthin
56f9e16a8b tests: viv: disable ELF tests due to #735 2021-08-23 17:51:28 -06:00
William Ballenthin
a4b0954532 viv: ignore mypy FP 2021-08-23 16:57:35 -06:00
William Ballenthin
fc73787849 extractors: file extractor arg consistency via kwargs 2021-08-23 16:42:16 -06:00
William Ballenthin
30a5493414 tests: smda: remove unused import 2021-08-23 16:13:01 -06:00
William Ballenthin
a729bdfbe6 elf: more clearly set first detected OS 2021-08-23 16:12:07 -06:00
William Ballenthin
dab88e482d elf: add more explanation about ei_osabi 2021-08-23 16:08:01 -06:00
William Ballenthin
6482f67a0c elf: document unused OS constants 2021-08-23 16:06:14 -06:00
William Ballenthin
a1bf95ec2c features: formatting of OS constants 2021-08-23 16:00:57 -06:00
William Ballenthin
6961fde327 Merge branch 'feature-701' of github.com:fireeye/capa into feature-701 2021-08-23 15:59:09 -06:00
William Ballenthin
c0fe0420fc changelog: tweak PR ref 2021-08-23 15:58:32 -06:00
Willi Ballenthin
2ba000a987 Merge branch 'master' into feature-701 2021-08-23 10:02:41 -06:00
Willi Ballenthin
a90e93e150 Update capa/main.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2021-08-23 08:54:43 -06:00
Willi Ballenthin
b6ab12d3c1 Update capa/features/common.py
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2021-08-23 08:54:22 -06:00
dependabot[bot]
71ccd87435 build(deps): bump networkx from 2.5.1 to 2.6.2
Bumps [networkx](https://github.com/networkx/networkx) from 2.5.1 to 2.6.2.
- [Release notes](https://github.com/networkx/networkx/releases)
- [Commits](https://github.com/networkx/networkx/compare/networkx-2.5.1...networkx-2.6.2)

---
updated-dependencies:
- dependency-name: networkx
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-23 14:24:19 +00:00
Willi Ballenthin
d07045f134 Merge pull request #731 from fireeye/dependabot/pip/vivisect-1.0.4
build(deps): bump vivisect from 1.0.3 to 1.0.4
2021-08-23 08:23:36 -06:00
dependabot[bot]
bede4a0aa1 build(deps): bump vivisect from 1.0.3 to 1.0.4
Bumps [vivisect](https://github.com/vivisect/vivisect) from 1.0.3 to 1.0.4.
- [Release notes](https://github.com/vivisect/vivisect/releases)
- [Changelog](https://github.com/vivisect/vivisect/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/vivisect/vivisect/compare/v1.0.3...v1.0.4)

---
updated-dependencies:
- dependency-name: vivisect
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-23 14:22:20 +00:00
Willi Ballenthin
de1cff356a Merge pull request #733 from fireeye/dependabot/pip/tqdm-4.62.2
build(deps): bump tqdm from 4.62.1 to 4.62.2
2021-08-23 08:21:56 -06:00
Willi Ballenthin
1bee098fb6 Merge pull request #734 from fireeye/dependabot/pip/smda-1.6.2
build(deps): bump smda from 1.5.19 to 1.6.2
2021-08-23 08:21:00 -06:00
dependabot[bot]
e36e175e08 build(deps): bump smda from 1.5.19 to 1.6.2
Bumps [smda](https://github.com/danielplohmann/smda) from 1.5.19 to 1.6.2.
- [Release notes](https://github.com/danielplohmann/smda/releases)
- [Commits](https://github.com/danielplohmann/smda/commits)

---
updated-dependencies:
- dependency-name: smda
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-23 14:20:55 +00:00
Willi Ballenthin
9db45d2fcb Merge pull request #732 from fireeye/dependabot/pip/ruamel-yaml-0.17.13
build(deps): bump ruamel-yaml from 0.17.10 to 0.17.13
2021-08-23 08:20:07 -06:00
dependabot[bot]
558f5d0c8a build(deps): bump tqdm from 4.62.1 to 4.62.2
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.62.1 to 4.62.2.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.62.1...v4.62.2)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-23 14:02:36 +00:00
dependabot[bot]
e32a887091 build(deps): bump ruamel-yaml from 0.17.10 to 0.17.13
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.10 to 0.17.13.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-23 14:02:32 +00:00
William Ballenthin
1b9a6c3c59 main: collect os/format/arch into metadata and render it 2021-08-20 16:50:40 -06:00
William Ballenthin
aef03b5592 elf: fix type error caught by mypy! 2021-08-20 15:00:06 -06:00
William Ballenthin
3eaeb533e9 Merge branch 'feature-701' of github.com:fireeye/capa into feature-701 2021-08-20 14:56:53 -06:00
William Ballenthin
04cc94a450 main: detect invalid arch and os 2021-08-20 14:56:26 -06:00
Willi Ballenthin
dae7be076d elf: fix alignment calculation
identified over [here](14f9c972b3 (r692441396))
2021-08-19 14:45:08 -06:00
Michael Hunhoff
3cb7573edb enable os/arch/format for capa explorer 2021-08-19 13:06:43 -06:00
William Ballenthin
a96a5de12d tests: re-enable SMDA ELF API tests 2021-08-19 08:02:17 -06:00
William Ballenthin
45b6c8dad3 setup: bump SMDA dep ver
closes #725
2021-08-19 08:01:17 -06:00
William Ballenthin
cf17ebac33 Merge branch 'feature-701' of github.com:fireeye/capa into feature-701 2021-08-18 16:33:21 -06:00
William Ballenthin
f0a34fdb5e merge 2021-08-18 16:32:58 -06:00
Willi Ballenthin
e124115e8d Merge branch 'master' into feature-701 2021-08-18 16:29:05 -06:00
William Ballenthin
249b8498d9 pefile: extract Arch 2021-08-18 16:27:41 -06:00
Capa Bot
15c69e3b7d Sync capa rules submodule 2021-08-18 21:15:01 +00:00
Capa Bot
98208b8eec Sync capa rules submodule 2021-08-18 20:50:11 +00:00
Capa Bot
0690e73320 Sync capa rules submodule 2021-08-18 20:38:06 +00:00
William Ballenthin
766ac7e500 Merge branch 'master' of github.com:fireeye/capa into feature-701 2021-08-18 14:33:17 -06:00
Capa Bot
51ac57c657 Sync capa-testfiles submodule 2021-08-18 20:33:02 +00:00
William Ballenthin
89603586da elf: add some doc 2021-08-18 14:23:48 -06:00
William Ballenthin
a35f5a1650 elf: detect FreeBSD via note 2021-08-18 14:21:50 -06:00
William Ballenthin
f1df29d27e tests: xfail smda ELF API
waiting for #725
2021-08-18 14:08:36 -06:00
Willi Ballenthin
08c24e2705 Merge pull request #729 from doomedraven/patch-1
update capa_as_library for capa v2
2021-08-18 08:32:41 -06:00
doomedraven
b1171864e3 black 2021-08-18 14:25:58 +02:00
doomedraven
5af59cecda update capa_as_library for capa v2 2021-08-18 14:23:36 +02:00
William Ballenthin
0c3a38b24b Merge branch 'feature-701' of github.com:fireeye/capa into feature-701 2021-08-17 09:07:25 -06:00
William Ballenthin
ac5d163aa0 pep8 2021-08-17 09:07:08 -06:00
Willi Ballenthin
dfe2dbea6d Merge pull request #722 from fireeye/fix-703
fix reporting of namespace matches
2021-08-17 09:05:19 -06:00
Willi Ballenthin
909ffc187b Merge branch 'master' into feature-701 2021-08-17 09:00:48 -06:00
William Ballenthin
92dfa99059 extractors: log unsupported os/arch/format but don't except 2021-08-17 08:57:42 -06:00
William Ballenthin
0065876702 extractors: ida: move os extraction to global module 2021-08-17 08:57:27 -06:00
Capa Bot
23bf28702f Sync capa rules submodule 2021-08-17 14:23:23 +00:00
Capa Bot
066873bd06 Sync capa rules submodule 2021-08-17 14:20:34 +00:00
William Ballenthin
98c00bd8b1 extractors: add missing global_.py files 2021-08-16 17:12:45 -06:00
William Ballenthin
fd47b03fac render: vverbose: don't render locations of global scope features 2021-08-16 17:12:28 -06:00
William Ballenthin
8e689c39f4 features: add Arch feature at global scope 2021-08-16 17:06:56 -06:00
William Ballenthin
738fa9150e fixtures: update tests to account for Format scope 2021-08-16 16:39:40 -06:00
William Ballenthin
5405e182c3 features: move Format features to file scope 2021-08-16 16:37:04 -06:00
William Ballenthin
ab1326f858 features: move OS and Format to their own features, not characteristics 2021-08-16 16:28:26 -06:00
William Ballenthin
f013815b2a features: rename legacy term arch to bitness
makes space for upcoming feature `arch: ` for things like i386/amd64/aarch64
2021-08-16 12:21:25 -06:00
Willi Ballenthin
5b24fc2543 Merge pull request #727 from fireeye/dependabot/pip/tqdm-4.62.1
build(deps): bump tqdm from 4.62.0 to 4.62.1
2021-08-16 08:22:44 -06:00
dependabot[bot]
b103e40ba8 build(deps): bump tqdm from 4.62.0 to 4.62.1
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.62.0 to 4.62.1.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.62.0...v4.62.1)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-16 14:02:16 +00:00
William Ballenthin
d5c9a5cf3c mypy: ignore ida_loader 2021-08-11 15:15:33 -06:00
William Ballenthin
30d7425b98 changelog 2021-08-11 15:10:07 -06:00
William Ballenthin
34819b289d pep8 2021-08-11 15:08:31 -06:00
William Ballenthin
71d9ebd859 extractors: ida: extract OS and file format characteristics at all scopes 2021-08-11 15:05:57 -06:00
William Ballenthin
c1910d47f0 move is_global_feature into capa.features.common 2021-08-11 15:02:10 -06:00
William Ballenthin
769d354792 detect-elf-os: remove extra print statement 2021-08-11 14:56:01 -06:00
William Ballenthin
a7678e779e extractors: smda: extract format and OS characteristics at all scopes 2021-08-11 14:52:36 -06:00
William Ballenthin
294f74b209 extractors: viv: extract format and OS at all scopes 2021-08-11 14:44:41 -06:00
William Ballenthin
fa8b4a4203 extractors: add common routine to extract OS from ELF 2021-08-11 14:43:13 -06:00
William Ballenthin
7205862dbf helpers: move ELF and IDA helpers out of script and into common module 2021-08-11 14:42:29 -06:00
William Ballenthin
37bc47c772 extractors: viv: extract from bytes not file path 2021-08-11 14:41:11 -06:00
William Ballenthin
baaa8ba2c1 scripts: add script to detect ELF OS
closes #724
2021-08-11 13:52:50 -06:00
William Ballenthin
05f8e2445a fixtures: add tests demonstrating extraction of features from ELF files 2021-08-11 09:29:05 -06:00
William Ballenthin
753b003107 pep8 2021-08-11 09:23:41 -06:00
William Ballenthin
97092c91db tests: assert absence of the wrong os/format 2021-08-11 09:13:56 -06:00
William Ballenthin
20859d2796 extractors: pefile: extract OS and format 2021-08-11 09:11:29 -06:00
William Ballenthin
06f8943bc4 features: add format/pe and format/elf characteristics 2021-08-11 09:10:04 -06:00
William Ballenthin
e797a67e97 features: define CHARACTERISTIC_OS constants for ease of use 2021-08-11 09:08:37 -06:00
William Ballenthin
a1eca58d7a features: support characteristic(os/*) features 2021-08-11 08:40:40 -06:00
William Ballenthin
aefe97e09e rules: fix typos 2021-08-11 08:39:56 -06:00
Willi Ballenthin
59ae901f57 changelog 2021-08-11 08:21:38 -06:00
Capa Bot
811f484d3b Sync capa-testfiles submodule 2021-08-11 14:18:28 +00:00
Willi Ballenthin
ff08b99190 Merge pull request #700 from Adir-Shemesh/elf
Add initial elf files support
2021-08-11 08:18:02 -06:00
William Ballenthin
44dc4efe57 changlog 2021-08-10 13:14:00 -06:00
William Ballenthin
f7e2ac83f2 Merge branch 'master' of github.com:fireeye/capa into fix-703 2021-08-10 13:12:25 -06:00
William Ballenthin
7e60162d65 result_document: extract only the relevant namespace locations
closes #703
2021-08-10 13:06:04 -06:00
William Ballenthin
cd06ee4544 main: correctly extract namespaces matches across scopes
closes #721
2021-08-10 13:05:31 -06:00
Willi Ballenthin
6d0a777de6 pefile: handle case where no name is exported
closes #684
2021-08-09 20:28:25 -06:00
Capa Bot
dd7a48a00c Sync capa rules submodule 2021-08-09 19:52:39 +00:00
Willi Ballenthin
582dcef097 Merge pull request #718 from fireeye/dependabot/pip/types-tabulate-0.8.2
build(deps-dev): bump types-tabulate from 0.8.0 to 0.8.2
2021-08-09 09:55:27 -06:00
dependabot[bot]
b9501d7b77 build(deps-dev): bump types-tabulate from 0.8.0 to 0.8.2
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.0 to 0.8.2.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-09 15:49:55 +00:00
Willi Ballenthin
a523fcf804 Merge pull request #717 from fireeye/dependabot/pip/types-termcolor-1.1.1
build(deps-dev): bump types-termcolor from 0.1.1 to 1.1.1
2021-08-09 09:49:16 -06:00
dependabot[bot]
cd07745af1 build(deps-dev): bump types-termcolor from 0.1.1 to 1.1.1
Bumps [types-termcolor](https://github.com/python/typeshed) from 0.1.1 to 1.1.1.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-termcolor
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-09 15:41:25 +00:00
Willi Ballenthin
6c15881bfe Merge pull request #716 from fireeye/dependabot/pip/types-pyyaml-5.4.6
build(deps-dev): bump types-pyyaml from 5.4.3 to 5.4.6
2021-08-09 09:40:40 -06:00
dependabot[bot]
7ff358ee00 build(deps-dev): bump types-pyyaml from 5.4.3 to 5.4.6
Bumps [types-pyyaml](https://github.com/python/typeshed) from 5.4.3 to 5.4.6.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-09 15:39:34 +00:00
Willi Ballenthin
79e5fad326 Merge pull request #715 from fireeye/dependabot/pip/types-colorama-0.4.3
build(deps-dev): bump types-colorama from 0.4.2 to 0.4.3
2021-08-09 09:38:48 -06:00
dependabot[bot]
93f5e966b2 build(deps-dev): bump types-colorama from 0.4.2 to 0.4.3
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.2 to 0.4.3.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-09 14:02:06 +00:00
adirshemesh
d0e9c004a0 Add initial elf files support 2021-08-05 15:24:22 +03:00
Capa Bot
4814a47560 Sync capa rules submodule 2021-08-03 14:10:25 +00:00
Willi Ballenthin
3c81d91072 Merge pull request #696 from fireeye/dependabot/pip/tqdm-4.62.0
build(deps): bump tqdm from 4.61.2 to 4.62.0
2021-08-02 08:43:26 -06:00
Willi Ballenthin
de21f9a1f9 Merge pull request #695 from fireeye/dependabot/pip/types-tabulate-0.8.0
build(deps-dev): bump types-tabulate from 0.1.1 to 0.8.0
2021-08-02 08:43:12 -06:00
Willi Ballenthin
9f4dab89a5 Merge pull request #694 from fireeye/dependabot/pip/isort-5.9.3
build(deps-dev): bump isort from 5.9.2 to 5.9.3
2021-08-02 08:43:01 -06:00
dependabot[bot]
9def3df16f build(deps): bump tqdm from 4.61.2 to 4.62.0
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.61.2 to 4.62.0.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.61.2...v4.62.0)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-02 14:02:28 +00:00
dependabot[bot]
44dd56e344 build(deps-dev): bump types-tabulate from 0.1.1 to 0.8.0
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.1.1 to 0.8.0.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-02 14:02:24 +00:00
dependabot[bot]
e630bd06db build(deps-dev): bump isort from 5.9.2 to 5.9.3
Bumps [isort](https://github.com/pycqa/isort) from 5.9.2 to 5.9.3.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.9.2...5.9.3)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-02 14:02:22 +00:00
Capa Bot
1fbd4937bc Sync capa rules submodule 2021-07-29 19:33:40 +00:00
Capa Bot
cc54bdddc6 Sync capa rules submodule 2021-07-29 18:44:43 +00:00
Capa Bot
f750455519 Sync capa rules submodule 2021-07-29 18:42:08 +00:00
mike-hunhoff
3d383bcc57 Merge pull request #692 from fireeye/explorer/enhance-limit-features-to-selection
add option to limit features to currently selected disassembly address
2021-07-29 09:20:36 -06:00
Michael Hunhoff
cdab6eaa5d updating CHANGELOG 2021-07-28 13:50:50 -06:00
Michael Hunhoff
7937cb6ea3 updating API calls 2021-07-28 13:44:06 -06:00
Michael Hunhoff
57f5236c9b adding option to filter features by currenty disassembly address 2021-07-28 13:38:36 -06:00
mike-hunhoff
f7bdd0e7f6 Merge pull request #691 from fireeye/fix/690
enforce max column width Features and Editor panes
2021-07-28 12:10:02 -06:00
Michael Hunhoff
a108e385fe updating changelog 2021-07-28 09:07:22 -06:00
Michael Hunhoff
6549c9878b merge upstream 2021-07-28 09:06:30 -06:00
Michael Hunhoff
a3a760e1e6 limit column sizes for Features and Editor panes 2021-07-28 08:53:12 -06:00
mike-hunhoff
576b9be78c Merge pull request #689 from fireeye/fix/544
add option to select specificed byte count for bytes feature
2021-07-27 16:12:26 -06:00
Michael Hunhoff
528548eb8c add option to select specificed byte count for bytes feature 2021-07-27 15:18:13 -06:00
mike-hunhoff
9a2415e34e Merge pull request #688 from fireeye/fix/514
update IDA extractor to use non-canon mnemonics
2021-07-27 14:56:14 -06:00
Michael Hunhoff
c9b7162a5f update IDA extractor to use non-canon mnemonics 2021-07-27 13:34:52 -06:00
mike-hunhoff
7fd9ab5e88 Merge pull request #687 from fireeye/fix/655
remove duplicate check when saving file
2021-07-27 10:49:23 -06:00
Michael Hunhoff
b44edbd90e remove duplicate check when saving file 2021-07-27 09:50:25 -06:00
mike-hunhoff
a1b3703a0d Merge pull request #686 from fireeye/fix/531
add additional filter logic when displaying capa matches by function
2021-07-27 08:48:35 -06:00
Michael Hunhoff
874dffc13f add additional filter logic when displaying capa matches by function 2021-07-26 17:37:35 -06:00
Capa Bot
8b572dc63f Sync capa rules submodule 2021-07-26 21:48:37 +00:00
Willi Ballenthin
659b29a62d Merge pull request #685 from fireeye/dependabot/pip/smda-1.5.19
build(deps): bump smda from 1.5.18 to 1.5.19
2021-07-26 09:22:22 -06:00
dependabot[bot]
7a558898e1 build(deps): bump smda from 1.5.18 to 1.5.19
Bumps [smda](https://github.com/danielplohmann/smda) from 1.5.18 to 1.5.19.
- [Release notes](https://github.com/danielplohmann/smda/releases)
- [Commits](https://github.com/danielplohmann/smda/commits)

---
updated-dependencies:
- dependency-name: smda
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-26 14:02:46 +00:00
Capa Bot
7dee553558 Sync capa rules submodule 2021-07-23 16:39:19 +00:00
Capa Bot
9f6f18466a Sync capa rules submodule 2021-07-22 06:56:23 +00:00
Capa Bot
ef003366da Sync capa-testfiles submodule 2021-07-21 07:12:59 +00:00
Moritz
aaaadc2a47 Update installation.md (#679)
* Update installation.md

* Update doc/installation.md

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2021-07-20 20:01:10 +02:00
Willi Ballenthin
f94287c9ae Merge pull request #678 from fireeye/mr-tz-patch-1
Update README.md
2021-07-19 14:31:37 -06:00
Moritz
c56bfdca67 Update README.md 2021-07-19 21:10:20 +02:00
Willi Ballenthin
77a86e33bd Merge pull request #671 from Ana06/release2
Release capa v2.0 🎉
2021-07-19 10:32:34 -06:00
Willi Ballenthin
4f44b5a60a Merge pull request #677 from fireeye/dependabot/pip/black-21.7b0
build(deps-dev): bump black from 21.6b0 to 21.7b0
2021-07-19 10:01:45 -06:00
dependabot[bot]
9361b3deb1 build(deps-dev): bump black from 21.6b0 to 21.7b0
Bumps [black](https://github.com/psf/black) from 21.6b0 to 21.7b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-19 14:02:42 +00:00
Ana Maria Martinez Gomez
9a0ec51f00 changelog: update date and number of rules 2021-07-16 17:37:03 +02:00
Ana Maria Martinez Gomez
5979892d29 version: capa v2.0
Prepare capa/version for capa 2.0 release.
2021-07-16 17:34:14 +02:00
Ana Maria Martinez Gomez
96f2536c34 changelog: capa v2.0
Prepare changelog for capa v2.0 release.
2021-07-16 17:34:13 +02:00
Capa Bot
52a3d35987 Sync capa rules submodule 2021-07-13 18:39:44 +00:00
Capa Bot
de4827e8fa Sync capa rules submodule 2021-07-13 18:34:24 +00:00
Capa Bot
b6d5409691 Sync capa rules submodule 2021-07-13 18:33:06 +00:00
Capa Bot
818f532ca9 Sync capa rules submodule 2021-07-13 18:31:57 +00:00
Capa Bot
895b548f34 Sync capa rules submodule 2021-07-13 03:09:36 +00:00
Willi Ballenthin
d9f1d0918f Merge pull request #675 from fireeye/dependabot/pip/isort-5.9.2
build(deps-dev): bump isort from 5.9.1 to 5.9.2
2021-07-12 10:33:16 -06:00
Willi Ballenthin
35abdb8ecf Merge pull request #674 from fireeye/dependabot/pip/tqdm-4.61.2
build(deps): bump tqdm from 4.61.1 to 4.61.2
2021-07-12 10:32:38 -06:00
dependabot[bot]
e77bbd68cf build(deps-dev): bump isort from 5.9.1 to 5.9.2
Bumps [isort](https://github.com/pycqa/isort) from 5.9.1 to 5.9.2.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.9.1...5.9.2)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-12 14:02:19 +00:00
dependabot[bot]
4c73e5df3c build(deps): bump tqdm from 4.61.1 to 4.61.2
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.61.1 to 4.61.2.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.61.1...v4.61.2)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-12 14:02:13 +00:00
Moritz
933789d02b Merge pull request #670 from fireeye/better-sig-loading
Better sig loading
2021-06-30 18:56:39 +02:00
Moritz Raabe
e88bb4814e update readme 2021-06-30 10:10:44 +02:00
Moritz
17b7694170 Merge pull request #666 from fireeye/fix-656
main: load signatures in order of their basename
2021-06-30 10:04:35 +02:00
Moritz Raabe
f191c4f145 wrap sig loading 2021-06-30 10:04:11 +02:00
Moritz Raabe
6fc2037f45 update sig file names 2021-06-30 08:54:37 +02:00
Moritz
b5f23e7baf Merge pull request #660 from fireeye/ci/test-scripts
test scripts and fix show-features
2021-06-29 21:46:43 +02:00
Capa Bot
f7e4273523 Sync capa rules submodule 2021-06-29 19:22:47 +00:00
Moritz Raabe
6860b9a040 address Willi's feedback 2021-06-29 21:16:31 +02:00
Moritz Raabe
5c8a4aafd7 test scripts and fix show-features 2021-06-29 21:16:31 +02:00
Moritz Raabe
02658d6962 do not process non-pe even with --format pe 2021-06-29 21:16:31 +02:00
William Ballenthin
b2b94e6a8e main: load signatures in order of their basename
closes #656
2021-06-29 10:52:07 -06:00
Moritz
65b3c046a3 Merge pull request #661 from fireeye/ida/extract-api-flirt
ida extract library funcs identified via flirt
2021-06-29 09:23:21 +02:00
Moritz Raabe
04b5949a05 address Mike's feedback 2021-06-29 08:57:43 +02:00
Moritz Raabe
18c87e4e55 ida extract library funcs identified via flirt 2021-06-29 08:49:48 +02:00
Willi Ballenthin
b84cc3128d Merge pull request #664 from fireeye/verify-pe-format
do not process non-pe even with --format pe
2021-06-28 12:09:54 -06:00
Willi Ballenthin
f83ef470cb Merge pull request #662 from fireeye/dependabot/pip/mypy-0.910
build(deps-dev): bump mypy from 0.902 to 0.910
2021-06-28 11:54:28 -06:00
Willi Ballenthin
2928dd279c Merge pull request #663 from fireeye/dependabot/pip/ruamel-yaml-0.17.10
build(deps): bump ruamel-yaml from 0.17.9 to 0.17.10
2021-06-28 11:54:15 -06:00
Moritz Raabe
f96d3fd8ba do not process non-pe even with --format pe 2021-06-28 18:21:01 +02:00
dependabot[bot]
d094272e4a build(deps): bump ruamel-yaml from 0.17.9 to 0.17.10
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.9 to 0.17.10.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-28 14:02:54 +00:00
dependabot[bot]
7eeab35ae8 build(deps-dev): bump mypy from 0.902 to 0.910
Bumps [mypy](https://github.com/python/mypy) from 0.902 to 0.910.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.902...v0.910)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-28 14:02:45 +00:00
Moritz
4e7b490bc3 Merge pull request #639 from fireeye/fix-630
more intuitive signature loading
2021-06-28 12:53:58 +02:00
Moritz Raabe
4ca9e168fe Merge branch 'master' into fix-630 2021-06-28 11:32:27 +02:00
Ana María Martínez Gómez
e579edecb4 Merge pull request #548 from Ana06/explorer-analyze
explorer: add analyze option
2021-06-24 12:22:24 +02:00
Capa Bot
58aa3e33bf Sync capa rules submodule 2021-06-24 00:33:45 +00:00
Ana Maria Martinez Gomez
0685d36220 explorer: use bitmask + enum for analyze option 2021-06-23 11:23:27 +02:00
Ana Maria Martinez Gomez
2158be0a2e explorer: add analyze option
I would like to load capa explorer with an script and that it runs the
analysis without needing extra clicks. Introduce an analyze option for
this.

Loading capa explorer from the UI or with Alt+F5 behaves as before. The
following command as well:
```
ida_loader.load_and_run_plugin("capa_explorer", 0)
```
But the following command automatically runs the analysis without extra
clicks:
```
ida_loader.load_and_run_plugin("capa_explorer", 1)
```

Example of where I am using this:
https://github.com/Ana06/idapython/blob/master/idapythonrc.py#L22
2021-06-23 11:23:27 +02:00
Moritz
7922d08fd4 Merge pull request #617 from fireeye/changelog-reorg
changelog: add breaking change section and reorg
2021-06-23 07:47:53 +02:00
Moritz Raabe
44b47eb39c update release checklist 2021-06-23 07:44:08 +02:00
Moritz Raabe
45c4b4019a move breaking changes to top 2021-06-23 07:44:05 +02:00
Moritz Raabe
831dc577f4 add breaking change section and reorg 2021-06-23 07:40:33 +02:00
Willi Ballenthin
229d5ca549 Merge pull request #654 from fireeye/fix/653
resolve circular import failure
2021-06-22 17:47:06 -06:00
Michael Hunhoff
2872db8b23 resolve circular import failure 2021-06-22 16:12:07 -06:00
Moritz
7152525dbc Merge pull request #648 from fireeye/mr-tz-patch-1
update dependabot actor name
2021-06-22 09:07:12 +02:00
Willi Ballenthin
d7d7aa76c8 Merge pull request #651 from fireeye/dependabot/pip/mypy-0.902
build(deps-dev): bump mypy from 0.901 to 0.902
2021-06-21 10:49:53 -06:00
dependabot[bot]
565bb96c9e build(deps-dev): bump mypy from 0.901 to 0.902
Bumps [mypy](https://github.com/python/mypy) from 0.901 to 0.902.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.901...v0.902)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 16:47:28 +00:00
Willi Ballenthin
9fd6098e1e Merge pull request #650 from fireeye/dependabot/pip/types-backports-0.1.3
build(deps-dev): bump types-backports from 0.1.2 to 0.1.3
2021-06-21 10:47:10 -06:00
Willi Ballenthin
0c0929fd94 Merge pull request #649 from fireeye/dependabot/pip/isort-5.9.1
build(deps-dev): bump isort from 5.8.0 to 5.9.1
2021-06-21 10:46:59 -06:00
Willi Ballenthin
1343baa250 Merge pull request #646 from fireeye/dependabot/pip/types-pyyaml-5.4.3
build(deps-dev): bump types-pyyaml from 0.1.6 to 5.4.3
2021-06-21 10:46:43 -06:00
dependabot[bot]
6977477a39 build(deps-dev): bump types-backports from 0.1.2 to 0.1.3
Bumps [types-backports](https://github.com/python/typeshed) from 0.1.2 to 0.1.3.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-backports
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 16:44:34 +00:00
dependabot[bot]
86b3438a2d build(deps-dev): bump isort from 5.8.0 to 5.9.1
Bumps [isort](https://github.com/pycqa/isort) from 5.8.0 to 5.9.1.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.8.0...5.9.1)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 16:44:34 +00:00
dependabot[bot]
a00c3b6d32 build(deps-dev): bump types-pyyaml from 0.1.6 to 5.4.3
Bumps [types-pyyaml](https://github.com/python/typeshed) from 0.1.6 to 5.4.3.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 16:44:34 +00:00
Willi Ballenthin
544ffdea8f Merge pull request #647 from fireeye/dependabot/pip/types-tabulate-0.1.1
build(deps-dev): bump types-tabulate from 0.1.0 to 0.1.1
2021-06-21 10:43:55 -06:00
dependabot[bot]
e4b89f1d7b build(deps-dev): bump types-tabulate from 0.1.0 to 0.1.1
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.1.0 to 0.1.1.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 16:43:23 +00:00
Willi Ballenthin
73dd49ed21 Merge pull request #645 from fireeye/dependabot/pip/viv-utils-flirt--0.6.5
build(deps): bump viv-utils[flirt] from 0.6.4 to 0.6.5
2021-06-21 10:43:11 -06:00
Willi Ballenthin
0511eec67c Merge pull request #644 from fireeye/dependabot/pip/types-termcolor-0.1.1
build(deps-dev): bump types-termcolor from 0.1.0 to 0.1.1
2021-06-21 10:42:56 -06:00
Willi Ballenthin
c7e2ca0b1a Merge pull request #643 from fireeye/dependabot/pip/types-colorama-0.4.2
build(deps-dev): bump types-colorama from 0.4.0 to 0.4.2
2021-06-21 10:42:46 -06:00
Capa Bot
03b15ce289 Sync capa rules submodule 2021-06-21 14:30:00 +00:00
Moritz
2d7ac73caa update dependabot actor name 2021-06-21 16:24:43 +02:00
dependabot[bot]
7fe53073fe build(deps): bump viv-utils[flirt] from 0.6.4 to 0.6.5
Bumps [viv-utils[flirt]](https://github.com/williballenthin/viv-utils) from 0.6.4 to 0.6.5.
- [Release notes](https://github.com/williballenthin/viv-utils/releases)
- [Commits](https://github.com/williballenthin/viv-utils/compare/v0.6.4...v0.6.5)

---
updated-dependencies:
- dependency-name: viv-utils[flirt]
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 14:02:11 +00:00
dependabot[bot]
d1407f0a1e build(deps-dev): bump types-termcolor from 0.1.0 to 0.1.1
Bumps [types-termcolor](https://github.com/python/typeshed) from 0.1.0 to 0.1.1.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-termcolor
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 14:02:08 +00:00
dependabot[bot]
f5a0e1cd08 build(deps-dev): bump types-colorama from 0.4.0 to 0.4.2
Bumps [types-colorama](https://github.com/python/typeshed) from 0.4.0 to 0.4.2.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 14:02:06 +00:00
Willi Ballenthin
94485285f3 Merge pull request #640 from fireeye/fix-507
disable viv creation by default
2021-06-15 15:06:40 -06:00
Willi Ballenthin
466bc4995b Update CHANGELOG.md
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2021-06-15 15:06:34 -06:00
William Ballenthin
7bce202122 doc: explain CAPA_SAVE_WORKSPACE 2021-06-15 12:31:56 -06:00
William Ballenthin
40c7401f0a pep8 2021-06-15 12:28:45 -06:00
William Ballenthin
a7ebd5a309 Merge branch 'master' of github.com:fireeye/capa into fix-507 2021-06-15 12:28:17 -06:00
William Ballenthin
d510840bb7 changelog 2021-06-15 12:26:37 -06:00
William Ballenthin
09ad0ec184 tests: save .viv by default, hopefully improve test performance 2021-06-15 12:24:29 -06:00
William Ballenthin
7f03db9fe4 main: dont save .viv by default, unless CAPA_SAVE_WORKSPACE set
closes #507
2021-06-15 12:24:01 -06:00
William Ballenthin
96b9bce93c Merge branch 'master' of github.com:fireeye/capa into fix-630 2021-06-15 11:59:25 -06:00
William Ballenthin
48858e114d main: refactor handling of rules, signatures cli arguments 2021-06-15 11:54:57 -06:00
William Ballenthin
1b4a087c4b render: don't stomp on meta dictionary
fixes a bug in bulk-process in which rules are evaluated multiple times
so meta cannot be updated in place.
2021-06-15 11:44:02 -06:00
William Ballenthin
6f1f928434 main: when --signatures provided, override default set
closes #630
2021-06-15 11:43:38 -06:00
Willi Ballenthin
efd02915ab Merge pull request #621 from fireeye/feature-447
add type annotations to public routines
2021-06-15 11:01:52 -06:00
William Ballenthin
9484fadd0f submodule sync data 2021-06-15 09:08:14 -06:00
Willi Ballenthin
b47b398b07 Merge pull request #636 from fireeye/fix-629
move test sigs into testfiles
2021-06-14 13:56:21 -06:00
Capa Bot
5867e880c6 Sync capa rules submodule 2021-06-14 19:41:57 +00:00
William Ballenthin
c1acf702b6 fixtures: move test sigs to testfiles 2021-06-14 11:37:39 -06:00
William Ballenthin
9a7c83b26f tests: move test sigs to testfiles 2021-06-14 11:36:53 -06:00
William Ballenthin
dd2671aac2 rules: fix types 2021-06-14 11:10:42 -06:00
William Ballenthin
c2981d5091 engine: cleanup some lints 2021-06-14 11:05:58 -06:00
William Ballenthin
ae2baebf6c import-to-bn: dont import * 2021-06-14 11:02:20 -06:00
William Ballenthin
7372aa91c6 engine: better type doc 2021-06-14 10:56:44 -06:00
William Ballenthin
48756a7621 ci: invoke mypy during testing 2021-06-14 10:41:53 -06:00
William Ballenthin
aca6ad2f52 scripts: fix types 2021-06-14 10:41:44 -06:00
William Ballenthin
24d61d8634 mypy: ignore more external deps 2021-06-14 10:41:32 -06:00
William Ballenthin
6411732bea rules: fix bug validating rules 2021-06-14 10:35:57 -06:00
William Ballenthin
152060a28a setup: move mypy deps in to capa[dev] target 2021-06-14 10:33:24 -06:00
William Ballenthin
919aef90c0 mypy: fix capa.features.common types 2021-06-14 10:33:08 -06:00
William Ballenthin
853d7285bd mypy: ignore ruamel 2021-06-14 10:32:51 -06:00
William Ballenthin
6842b92ca2 pep8 2021-06-14 10:25:37 -06:00
William Ballenthin
dba250ca86 rules: fix types and document description parsing 2021-06-14 10:25:15 -06:00
William Ballenthin
b8c524d2f5 type: capa.rules parse range 2021-06-14 10:09:35 -06:00
William Ballenthin
0ff5db9397 type: capa.rules feature validation 2021-06-14 10:06:48 -06:00
William Ballenthin
15334cf5d4 render: further refactor att&ck handling 2021-06-14 09:53:36 -06:00
William Ballenthin
f5cb5d462d render: further cleanup rendering of att&ck 2021-06-14 09:52:32 -06:00
William Ballenthin
79459d4a14 mypy fixes
type checker doesn't like a list that contains tuples with both
length 2 and length 3. so keep length constant with None values.
2021-06-14 09:50:12 -06:00
William Ballenthin
addd4683ca mypy fixes 2021-06-14 09:47:51 -06:00
William Ballenthin
6d8399684b type: capa.render 2021-06-14 09:28:33 -06:00
William Ballenthin
4583692539 type: capa.main 2021-06-14 09:19:08 -06:00
William Ballenthin
9b7e67443b extractors: fix type hints 2021-06-14 08:59:23 -06:00
William Ballenthin
83909b2be4 *: remove explicit object super class
closes #635
2021-06-14 08:47:09 -06:00
William Ballenthin
247d330f79 type: capa.features.extractors.base_extractor 2021-06-14 08:44:48 -06:00
Willi Ballenthin
1a31c84eef Merge pull request #632 from fireeye/dependabot/pip/black-21.6b0
build(deps-dev): bump black from 21.5b2 to 21.6b0
2021-06-14 08:20:53 -06:00
Willi Ballenthin
9ce92cfb5b Merge pull request #633 from fireeye/dependabot/pip/ruamel-yaml-0.17.9
build(deps): bump ruamel-yaml from 0.17.7 to 0.17.9
2021-06-14 08:20:31 -06:00
Willi Ballenthin
1f44a2dec8 Merge pull request #634 from fireeye/dependabot/pip/tqdm-4.61.1
build(deps): bump tqdm from 4.61.0 to 4.61.1
2021-06-14 08:20:19 -06:00
dependabot[bot]
b7cd467363 build(deps): bump tqdm from 4.61.0 to 4.61.1
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.61.0 to 4.61.1.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.61.0...v4.61.1)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-14 05:59:01 +00:00
dependabot[bot]
ff3cc421eb build(deps): bump ruamel-yaml from 0.17.7 to 0.17.9
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.7 to 0.17.9.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-14 05:58:55 +00:00
dependabot[bot]
205798865d build(deps-dev): bump black from 21.5b2 to 21.6b0
Bumps [black](https://github.com/psf/black) from 21.5b2 to 21.6b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-14 05:58:48 +00:00
Capa Bot
10f499d230 Sync capa rules submodule 2021-06-14 03:51:14 +00:00
William Ballenthin
a21b53d737 Merge branch 'master' of github.com:fireeye/capa into feature-447 2021-06-10 09:02:39 -06:00
Capa Bot
0f15895b36 Sync capa rules submodule 2021-06-10 14:42:56 +00:00
Moritz
2ba2aec0d3 Merge pull request #624 from fireeye/fix-622
remove logic from __init__.py and break import cycles
2021-06-10 13:53:10 +02:00
William Ballenthin
11d50aa5b1 pep8 2021-06-10 00:29:23 -06:00
William Ballenthin
b066af9506 mypy: extend lib ignore config 2021-06-10 00:28:28 -06:00
William Ballenthin
059909c027 features: fix types 2021-06-10 00:23:01 -06:00
William Ballenthin
d61ff0c69f changelog 2021-06-10 00:08:00 -06:00
William Ballenthin
f6c2394bdf common: fix type annotations 2021-06-10 00:07:05 -06:00
William Ballenthin
df5ed6bbf2 indirect_calls: fix types 2021-06-10 00:02:23 -06:00
William Ballenthin
0b653aa47a ida: file: fix imports 2021-06-10 00:02:11 -06:00
William Ballenthin
b5a18de4a3 pep8 2021-06-09 23:52:15 -06:00
William Ballenthin
5408481606 type: capa.engine 2021-06-09 23:51:55 -06:00
William Ballenthin
1c66ebe638 type: capa.features.common 2021-06-09 23:47:06 -06:00
William Ballenthin
3e79dfd0e7 type: capa.rules 2021-06-09 23:39:07 -06:00
William Ballenthin
459df37b13 indirect_calls: fix typing circular dependencies 2021-06-09 23:28:05 -06:00
William Ballenthin
3d8edc513c type: capa.features.extractors.viv.insn 2021-06-09 23:24:51 -06:00
William Ballenthin
ab7bf53f67 type: capa.features.insn 2021-06-09 23:20:46 -06:00
William Ballenthin
c30a56bc11 type: capa.features.extractors.helpers 2021-06-09 23:19:36 -06:00
William Ballenthin
6918a039e9 type: capa.render.result_document 2021-06-09 23:15:45 -06:00
William Ballenthin
469e2ff870 type: capa.features.extractors.viv.basicblock 2021-06-09 23:12:07 -06:00
William Ballenthin
3416f7bc61 type: capa.features.file 2021-06-09 23:09:24 -06:00
William Ballenthin
a75d7576f8 type: capa.features.extractors.viv.indirect_calls 2021-06-09 23:08:29 -06:00
William Ballenthin
23addda29a type: capa.render.utils 2021-06-09 23:06:33 -06:00
William Ballenthin
14e2efa309 type: capa.features.extractors.viv.file 2021-06-09 23:01:14 -06:00
William Ballenthin
faa363cd8f type: capa.render.default 2021-06-09 22:59:54 -06:00
William Ballenthin
e29922af57 type: capa.features.extractors.pefile 2021-06-09 22:56:02 -06:00
William Ballenthin
8a0ae7ae55 type: capa.features.extractors.viv.helpers 2021-06-09 22:54:29 -06:00
William Ballenthin
6f67619621 type capa.features.freeze 2021-06-09 22:51:09 -06:00
William Ballenthin
3f55f678ca Merge branch 'fix-622' into feature-447 2021-06-09 22:41:10 -06:00
William Ballenthin
ee41d47e4d test_function_id: fix test imports 2021-06-09 22:35:26 -06:00
William Ballenthin
527e993bb4 engine: remove dependency on rules, fixing circular import 2021-06-09 22:30:43 -06:00
William Ballenthin
6b4d7266e6 changelog 2021-06-09 22:23:06 -06:00
William Ballenthin
954ed3a408 pep8 2021-06-09 22:22:03 -06:00
William Ballenthin
ac59e50b5f move capa/features/__init__.py logic to common.py
also cleanup imports across the board,
thanks to pylance.
2021-06-09 22:20:53 -06:00
William Ballenthin
7029ad32c4 move capa/features/extractors/__init__.py logic to base_extractor.py 2021-06-09 21:09:29 -06:00
William Ballenthin
766dcacdbe move logic out of capa/render/__init__.py 2021-06-09 18:06:51 -06:00
William Ballenthin
fc9ad6c737 move extractors/ida/__init__.py logic to extractor.py 2021-06-09 17:55:44 -06:00
William Ballenthin
7d2e664320 move extractors/smda/__init__.py logic to extractor.py 2021-06-09 17:52:06 -06:00
William Ballenthin
6187317a4e move extractors/viv/__init__.py logic to extractor.py 2021-06-09 17:49:50 -06:00
William Ballenthin
d81b0bcbfa move helpers/__init__.py to helpers.py 2021-06-09 17:43:58 -06:00
William Ballenthin
9c8e18acb4 pefile/__init__ to pefile.py 2021-06-09 17:42:46 -06:00
William Ballenthin
8aed58c1d4 *: remove __all__
closes #623
2021-06-09 17:38:57 -06:00
William Ballenthin
325c726f0e typing: capa.helpers 2021-06-09 15:09:37 -06:00
William Ballenthin
9a4e9b6586 setup: add initial mypy setup
invoke like: mypy --config-file .github/mypy/mypy.ini capa/main.py
2021-06-09 14:50:37 -06:00
Capa Bot
23354ec452 Sync capa rules submodule 2021-06-09 09:19:50 +00:00
Capa Bot
f698f4e79b Sync capa rules submodule 2021-06-09 08:08:12 +00:00
Moritz
c05a8bf910 Merge pull request #620 from fireeye/fix-619
correctly render negative numbers and offsets
2021-06-09 10:03:04 +02:00
Moritz
9ffbb82f4c Merge pull request #618 from fireeye/fix/616
fix 616
2021-06-09 10:00:04 +02:00
William Ballenthin
0508d31a35 changelog 2021-06-08 11:10:40 -06:00
William Ballenthin
901a398b31 insn: render negative number, offset correctly
closes #619
2021-06-08 11:09:32 -06:00
mike-hunhoff
fd0f87ca6e Update capa/features/file.py w/ PR changes
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2021-06-08 10:59:42 -06:00
Michael Hunhoff
84d2f9f324 fix 616 2021-06-08 10:16:54 -06:00
Capa Bot
f9bad7e5e4 Sync capa rules submodule 2021-06-08 14:17:39 +00:00
Capa Bot
40b6575db6 Sync capa-testfiles submodule 2021-06-08 12:48:33 +00:00
Willi Ballenthin
64d849aafc Merge pull request #613 from fireeye/doc/update-readme
update readme
2021-06-07 10:46:28 -06:00
Willi Ballenthin
3b6e6dcc00 Merge pull request #612 from fireeye/ci/no-changelog-dependabot
ignore dependabot for changelog check
2021-06-07 10:45:56 -06:00
Willi Ballenthin
d17ac2928f Merge pull request #615 from fireeye/bump-smda
bump smda and remove xfail
2021-06-07 10:33:21 -06:00
Moritz Raabe
8b58723f40 bump smda and remove xfail 2021-06-07 13:56:55 +02:00
Moritz Raabe
bed2e3777e job level exclusion 2021-06-07 12:38:03 +02:00
Capa Bot
c039e98d3f Sync capa rules submodule 2021-06-07 09:51:13 +00:00
Moritz Raabe
c3ba6a9025 update readme 2021-06-07 10:26:41 +02:00
Moritz
2691fb400e Merge pull request #611 from fireeye/dependabot/pip/pytest-cov-2.12.1
build(deps-dev): bump pytest-cov from 2.12.0 to 2.12.1
2021-06-07 09:55:12 +02:00
Moritz
e0075573d9 Merge pull request #610 from fireeye/dependabot/pip/ruamel-yaml-0.17.7
build(deps): bump ruamel-yaml from 0.17.5 to 0.17.7
2021-06-07 09:55:00 +02:00
Moritz
1bb8c78b60 Merge pull request #609 from fireeye/dependabot/pip/black-21.5b2
build(deps-dev): bump black from 21.5b1 to 21.5b2
2021-06-07 09:54:40 +02:00
Moritz Raabe
ff66346d2a ignore dependabot for changelog check 2021-06-07 09:52:46 +02:00
Capa Bot
6f51324cca Sync capa-testfiles submodule 2021-06-07 07:45:31 +00:00
Capa Bot
700259eab6 Sync capa rules submodule 2021-06-07 07:45:04 +00:00
Capa Bot
438677b129 Sync capa-testfiles submodule 2021-06-07 06:48:11 +00:00
Capa Bot
3f51e787e4 Sync capa rules submodule 2021-06-07 06:19:37 +00:00
Capa Bot
2bbf00d603 Sync capa rules submodule 2021-06-07 06:17:47 +00:00
Moritz
b21b041dab Merge pull request #608 from fireeye/fix-605
fix 605
2021-06-07 08:16:16 +02:00
Moritz
734b1702e6 Merge pull request #607 from Ana06/ahead-changed-files
Use Ana06/get-changed-files@v1.2
2021-06-07 08:11:27 +02:00
dependabot[bot]
a39e2e7e0f build(deps-dev): bump pytest-cov from 2.12.0 to 2.12.1
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.12.0 to 2.12.1.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.12.0...v2.12.1)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-07 06:02:46 +00:00
dependabot[bot]
d9e1732766 build(deps): bump ruamel-yaml from 0.17.5 to 0.17.7
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.5 to 0.17.7.

---
updated-dependencies:
- dependency-name: ruamel-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-07 06:02:38 +00:00
dependabot[bot]
6dd5bbeffd build(deps-dev): bump black from 21.5b1 to 21.5b2
Bumps [black](https://github.com/psf/black) from 21.5b1 to 21.5b2.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-07 06:02:31 +00:00
William Ballenthin
3c4388e280 changelog 2021-06-04 11:48:03 -06:00
Ana Maria Martinez Gomez
6ffa5ef53e changelog: fix number of new rules
This was caused by a bug in the GH action which updates this number
automatically:
https://github.com/fireeye/capa-rules/pull/405
2021-06-04 19:47:57 +02:00
William Ballenthin
90ec848bf6 main: fix matching BB features at file scope
closes #605
2021-06-04 11:45:37 -06:00
William Ballenthin
e0be7f1b8e main: debug rules more correctly 2021-06-04 11:31:19 -06:00
Ana Maria Martinez Gomez
4ef3830b6b Use Ana06/get-changed-files@v1.2
Use Ana06/get-changed-files@v1.2 which removes the _head commit is ahead
of the base commit_ check. This made the action failed in not up-to-date
branches (in which rebasing is needed).

It supersedes https://github.com/fireeye/capa/pull/599
2021-06-04 14:03:41 +02:00
Ana María Martínez Gómez
e737595339 Merge pull request #604 from Ana06/lint_changelog
ci: lint CHANGELOG
2021-06-04 13:33:11 +02:00
Capa Bot
94cb090afe Sync capa rules submodule 2021-06-04 09:10:09 +00:00
Moritz
32e0a5dce2 Merge pull request #598 from fireeye/render/json-attck-fields
parse att&ck for output doc
2021-06-02 16:54:31 +02:00
Ana Maria Martinez Gomez
f304bdbd20 ci: lint CHANGELOG
The sync GH action in capa-rules relies on a single '- *$' in the
CHANGELOG file. Check in the tests that this is the case to avoid that
it is removed.

This happened in the following PR:
https://github.com/fireeye/capa/pull/591
This caused that the new rules in the following PR were not added to the
CHANGELOG:
https://github.com/fireeye/capa-rules/pull/400
2021-06-02 12:42:48 +02:00
Ana Maria Martinez Gomez
1a3286beda ci: fix CHANGELOG
The `-` used by the GitHub actions which updates the rules in the
CHANGELOG was removed in:
https://github.com/fireeye/capa/pull/591
Consequently the new rules added in the last pull request were not added
to the CHANGELOG:
https://github.com/fireeye/capa-rules/pull/400
2021-06-02 12:12:48 +02:00
Moritz Raabe
63cd70029f dedup code 2021-06-02 11:06:49 +02:00
Moritz Raabe
94089ff43f parse att&ck for output doc 2021-06-02 10:37:19 +02:00
Capa Bot
8f1ce68e96 Sync capa rules submodule 2021-06-01 17:51:43 +00:00
Willi Ballenthin
37208aabd3 Merge pull request #591 from fireeye/feature-590
main: use rule scope internal/limitation/file for file limitations, not code
2021-06-01 11:50:56 -06:00
Willi Ballenthin
8c3605c886 Merge branch 'master' into feature-590 2021-06-01 11:50:40 -06:00
William Ballenthin
2706a7171e linter: fix match namespace handling
closes #601
2021-06-01 11:38:05 -06:00
William Ballenthin
8f3d443247 rules: use existing code, dedup 2021-06-01 11:25:38 -06:00
Willi Ballenthin
9968d16f21 Merge pull request #593 from fireeye/feature-159
json: capture all strings matching regex
2021-06-01 11:18:08 -06:00
Willi Ballenthin
2756c05889 Merge branch 'master' into feature-159 2021-06-01 11:17:41 -06:00
William Ballenthin
8a65c565a5 pep8 2021-06-01 11:06:12 -06:00
William Ballenthin
17eeecc526 render: handle namespace matches in result document 2021-05-31 10:28:11 -06:00
William Ballenthin
3b245ea201 rules: index rules by namespace 2021-05-31 10:28:00 -06:00
William Ballenthin
3cd348e8f7 rules: implement __contains__ for RuleSet 2021-05-31 10:27:44 -06:00
William Ballenthin
6d08695b38 Merge branch 'master' of github.com:fireeye/capa into feature-590 2021-05-31 09:54:33 -06:00
William Ballenthin
66b2c07af4 main: show matching file limitation rule when showing warning 2021-05-31 09:53:19 -06:00
Capa Bot
b8a67553d0 Sync capa rules submodule 2021-05-31 08:53:38 +00:00
Moritz
82eae4324e Merge pull request #595 from fireeye/dependabot/pip/ruamel-yaml-0.17.5
build(deps): bump ruamel-yaml from 0.17.4 to 0.17.5
2021-05-31 10:39:33 +02:00
Moritz
ac9c132c91 Merge pull request #594 from fireeye/dependabot/pip/tqdm-4.61.0
build(deps): bump tqdm from 4.60.0 to 4.61.0
2021-05-31 10:39:14 +02:00
Moritz
c2953b9733 Merge pull request #576 from fireeye/render/json-mbc-attck-fields
render `rule.meta.mbc` on output
2021-05-31 10:38:27 +02:00
Moritz
30de93b81f Merge pull request #596 from fireeye/tests/fix-smda-fails
fix smda test xfail
2021-05-31 10:37:43 +02:00
Moritz Raabe
e6f45b63d6 fix test xfail 2021-05-31 10:02:31 +02:00
dependabot[bot]
c1b689a375 build(deps): bump ruamel-yaml from 0.17.4 to 0.17.5
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.4 to 0.17.5.

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-31 05:57:42 +00:00
dependabot[bot]
c1546cf6a8 build(deps): bump tqdm from 4.60.0 to 4.61.0
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.60.0 to 4.61.0.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.60.0...v4.61.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-31 05:57:33 +00:00
Moritz Raabe
de96bb763b address code review 2021-05-28 16:52:17 +02:00
Moritz Raabe
9e62bd1b24 update renderers 2021-05-28 16:40:15 +02:00
Moritz Raabe
54d21a043e parse mbc for result doc 2021-05-28 16:40:15 +02:00
Moritz Raabe
f593592ff0 parse mbc fields 2021-05-28 16:40:15 +02:00
Willi Ballenthin
ed02088c82 detect (and short circuit) file limitations at file scope (#586)
* smda: move pe carve into helpers

* smda: simplify test parametrization/xfail

* extractors: add pefile extractor for file scope features

* pep8

* main: bail early on file limitation detected at file scope

closes #583

* changelog
2021-05-28 08:14:44 -06:00
Ana María Martínez Gómez
b3fff51002 Merge pull request #584 from Ana06/changelog-GA
ci: Reject PRs without CHANGELOG update
2021-05-28 12:09:06 +02:00
Ana Maria Martinez Gomez
51884fea2d doc: Fix link and add more details
Fix broken link to `pull_request_template.md` and add some more details.

Related #457
2021-05-28 12:07:21 +02:00
Ana Maria Martinez Gomez
84b0bc6439 changelog: Add #584 to CHANGELOG 2021-05-28 11:08:05 +02:00
Ana Maria Martinez Gomez
38d41e2f59 ci: fix get-changed-files
Ana06/get-changed-files@v1.1 is a fork of
https://github.com/jitterbit/get-changed-files, which supports
`pull_request_target` and allow to filter files using regular
expressions.

As we need to use `pull_request_target`, Ana06/get-changed-files@v1.1
works, but jitterbit/get-changed-files@v1 doesn't.
2021-05-28 11:08:04 +02:00
Ana Maria Martinez Gomez
23ff9e719f ci: only reject once and fix dismiss
`Ana06/automatic-pull-request-review@v0.1.0` is a fork of
https://github.com/AndrewMusgrave/automatic-pull-request-review which
fixes `DISMISS` and provides an `allow_duplicate` option which allows to
only approve once.
2021-05-28 11:08:04 +02:00
Ana Maria Martinez Gomez
7a0a6f9cf1 ci: check changelog
Request changes in a PR without CHANGELOG update.
2021-05-28 11:08:04 +02:00
Ana Maria Martinez Gomez
f6960e4deb github: Improve pull request template
After using the PR template for a while, I think simplifying it will be
helpful:

- GitHub includes the commit message description automatically with the
aim of saving you time as it is sometimes also a good PR description.
With the current template, I need to cut this test and paste it into the
description section (which is really annoying!).

- Make a single simpler checklist. Add information as comment and have a
straightforward list which helps us remembering the changelog, tests and
documentation without needing to invest much time. The changelog
bulletpoint will also be used in GitHub Actions.
2021-05-28 11:08:00 +02:00
Willi Ballenthin
bd63ded1dd file scope API features (#568)
* smda: minor unrelated fixes

* file features: extract API features at file scope for library functions

closes #567

* changelog

* ida: add file-scope API feature

Co-authored-by: mike-hunhoff <mike.hunhoff@gmail.com>

* fix lints from pylance

* features: use "function-name" for recognized linked functions

* pep8

* pep8

* rules: remove incorrect feature scope

* tests: xfail SMDA tests relying on function id

* tests: fixtures: order tests by sample, ideally improving memory usage

* pep8

* pep8

* smda: xfail two more tests

Co-authored-by: mike-hunhoff <mike.hunhoff@gmail.com>
2021-05-27 12:59:00 -06:00
William Ballenthin
3c90e909a1 pep8 2021-05-27 10:45:01 -06:00
William Ballenthin
70396ffa36 ida: try to fix regex match rendering 2021-05-27 10:38:40 -06:00
William Ballenthin
56efb2adfe changelog 2021-05-27 10:28:41 -06:00
William Ballenthin
868b5ed6a3 features: extract all strings matching regex
closes #159
2021-05-27 10:27:39 -06:00
William Ballenthin
0a226e8b01 main: use rule scope internal/limitation/file for file limitations, not
code

closes #390
2021-05-27 09:18:55 -06:00
Capa Bot
7df29b491c Sync capa-testfiles submodule 2021-05-27 07:08:00 +00:00
Capa Bot
f0fb5fb346 Sync capa rules submodule 2021-05-26 21:03:50 +00:00
Capa Bot
342497b72f Sync capa rules submodule 2021-05-26 07:31:49 +00:00
Capa Bot
2b19257c5c Sync capa-testfiles submodule 2021-05-26 07:22:40 +00:00
Moritz
4ebbdcd00c Merge pull request #582 from fireeye/ci/lint-color-optional
or/optional lint and colors
2021-05-25 17:26:23 +02:00
Moritz Raabe
204d8b36df add or/optional lint and colors
closes #348
2021-05-25 16:32:47 +02:00
Moritz Raabe
8e4e9fc616 Revert "Sync capa-testfiles submodule"
This reverts commit 826d472c07.
2021-05-25 14:58:01 +02:00
Capa Bot
826d472c07 Sync capa-testfiles submodule 2021-05-25 12:45:59 +00:00
Capa Bot
57f416d62d Sync capa-testfiles submodule 2021-05-25 12:44:13 +00:00
Capa Bot
a79a547682 Sync capa rules submodule 2021-05-24 15:25:44 +00:00
Capa Bot
bd9812cee4 Sync capa rules submodule 2021-05-24 15:22:21 +00:00
Willi Ballenthin
2a36894d85 Merge pull request #578 from fireeye/dependabot/pip/viv-utils-flirt--0.6.4
build(deps): bump viv-utils[flirt] from 0.6.2 to 0.6.4
2021-05-24 09:14:31 -06:00
Willi Ballenthin
c33c4c45dc Merge pull request #577 from fireeye/dependabot/pip/smda-1.5.17
build(deps): bump smda from 1.5.14 to 1.5.17
2021-05-24 09:14:22 -06:00
dependabot[bot]
9cd07a0cee build(deps): bump viv-utils[flirt] from 0.6.2 to 0.6.4
Bumps [viv-utils[flirt]](https://github.com/williballenthin/viv-utils) from 0.6.2 to 0.6.4.
- [Release notes](https://github.com/williballenthin/viv-utils/releases)
- [Commits](https://github.com/williballenthin/viv-utils/compare/v0.6.2...v0.6.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 06:03:22 +00:00
dependabot[bot]
4f85d85ea6 build(deps): bump smda from 1.5.14 to 1.5.17
Bumps [smda](https://github.com/danielplohmann/smda) from 1.5.14 to 1.5.17.
- [Release notes](https://github.com/danielplohmann/smda/releases)
- [Commits](https://github.com/danielplohmann/smda/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 06:03:15 +00:00
Willi Ballenthin
8699003597 Merge pull request #572 from fireeye/feature-571
linter: summarize status at end
2021-05-21 11:14:29 -06:00
Willi Ballenthin
4cada67b21 Merge branch 'master' into feature-571 2021-05-21 11:14:22 -06:00
Willi Ballenthin
0a203b54cd changelog 2021-05-21 11:13:48 -06:00
Willi Ballenthin
cf1e9dc425 Merge pull request #573 from fireeye/lazy-import-flirt
lazy import flirt
2021-05-21 09:50:14 -06:00
Willi Ballenthin
6b8bb0520d Merge pull request #575 from ruppde/master
Update capa2yara.py
2021-05-21 09:45:24 -06:00
Arnim Rupp
7759d2dd79 Update capa2yara.py 2021-05-21 17:04:16 +02:00
Arnim Rupp
73f121cf03 Update capa2yara.py
bugfix: https://github.com/fireeye/capa-rules/blob/master/collection/get-geographical-location.yml hit an far too many files with /\bcity opposed to the intention of the capa rule ti just hit in function names. changed to /\x00city.
2021-05-21 16:51:14 +02:00
Moritz
91f914f5c0 Merge pull request #562 from fireeye/lib-meta-info
improve progress bar output
2021-05-21 16:47:52 +02:00
Moritz Raabe
af5613250f lazy import flirt
closes #540
2021-05-21 11:31:37 +02:00
Capa Bot
72da8f3aed Sync capa rules submodule 2021-05-21 07:12:57 +00:00
Moritz Raabe
a8e353fe31 revert rule loading pbar 2021-05-20 14:00:01 +02:00
Moritz Raabe
8a386b6909 improve progress bar output 2021-05-20 13:56:29 +02:00
Ana Maria Martinez Gomez
83606bbc0f changelog: convert capa rules to YARA rules
Add https://github.com/fireeye/capa/pull/561 to CHANGELOG.
2021-05-20 11:25:24 +02:00
Moritz
caaeded278 Merge pull request #563 from fireeye/ci/lint-statement-children
lint statements for single child statements
2021-05-20 10:41:41 +02:00
Willi Ballenthin
dcf4a056ee show-features: skip library functions (#570)
* show-features: skip library functions

closes #569

* changelog
2021-05-20 10:34:48 +02:00
Capa Bot
f9cec64c2d Sync capa-testfiles submodule 2021-05-20 08:11:28 +00:00
William Ballenthin
9b1400c23a pep8 2021-05-19 16:14:37 -06:00
William Ballenthin
60d77759f2 Merge branch 'feature-571' of github.com:fireeye/capa into feature-571 2021-05-19 16:14:09 -06:00
Willi Ballenthin
5fc705856d Merge branch 'master' into feature-571 2021-05-20 16:40:37 -06:00
William Ballenthin
0a1adb99e0 lint: cleanup handling of nursery rules further 2021-05-19 16:13:45 -06:00
William Ballenthin
3eef034a94 lint: better handling of nursery rule summary 2021-05-19 16:06:07 -06:00
Capa Bot
66d96201cb Sync capa rules submodule 2021-05-19 20:31:48 +00:00
Moritz Raabe
586726fb13 lint statements for single child statements 2021-05-19 18:25:14 +02:00
Capa Bot
656cdfc41c Sync capa rules submodule 2021-05-19 16:21:47 +00:00
Arnim Rupp
7b62b589f7 Create capa2yara.py (#561)
* Create capa2yara.py

* Update capa2yara.py

    isort --profile black --length-sort --line-width 120

    black -l 120

* Update scripts/capa2yara.py

Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>

Co-authored-by: Arnim Rupp <46819580+2d4d@users.noreply.github.com>
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2021-05-19 18:01:04 +02:00
Capa Bot
e7884c9a53 Sync capa rules submodule 2021-05-19 07:50:11 +00:00
William Ballenthin
2f2849dee0 changelog 2021-05-18 15:20:54 -06:00
William Ballenthin
ff88393248 linter: summarize status at end
closes #571
2021-05-18 15:19:34 -06:00
William Ballenthin
9ed6e12e7c Merge branch 'master' of github.com:fireeye/capa 2021-05-18 13:35:59 -06:00
William Ballenthin
ec5cec619d rules: add tests demonstrating mnemonic descriptions 2021-05-18 13:35:24 -06:00
Capa Bot
760867b81e Sync capa rules submodule 2021-05-17 15:00:45 +00:00
Capa Bot
abeaac0675 Sync capa rules submodule 2021-05-17 10:14:49 +00:00
Moritz
010866a3bd Merge pull request #560 from fireeye/dependabot/pip/pytest-cov-2.12.0
build(deps-dev): bump pytest-cov from 2.11.1 to 2.12.0
2021-05-17 12:14:16 +02:00
Capa Bot
8f9f792930 Sync capa rules submodule 2021-05-17 08:36:26 +00:00
Capa Bot
9ccdce9896 Sync capa rules submodule 2021-05-17 08:35:45 +00:00
dependabot[bot]
0dc212f53e build(deps-dev): bump pytest-cov from 2.11.1 to 2.12.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.11.1 to 2.12.0.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.11.1...v2.12.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-17 05:57:20 +00:00
Capa Bot
3cf4a47773 Sync capa rules submodule 2021-05-12 14:23:14 +00:00
Capa Bot
bbf59d65ad Sync capa rules submodule 2021-05-12 12:14:30 +00:00
Moritz
6b738f754e Merge pull request #557 from fireeye/dependabot/pip/black-21.5b1
build(deps-dev): bump black from 21.4b2 to 21.5b1
2021-05-12 07:35:43 +02:00
dependabot[bot]
83a4e054d1 build(deps-dev): bump black from 21.4b2 to 21.5b1
Bumps [black](https://github.com/psf/black) from 21.4b2 to 21.5b1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 17:42:03 +00:00
Moritz
9843776460 Merge pull request #552 from fireeye/dependabot/pip/pytest-6.2.4
build(deps-dev): bump pytest from 6.2.3 to 6.2.4
2021-05-11 19:40:43 +02:00
dependabot[bot]
2626572ddc build(deps-dev): bump pytest from 6.2.3 to 6.2.4
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.3 to 6.2.4.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.3...6.2.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 16:51:23 +00:00
Moritz
e3af23f209 Merge pull request #551 from fireeye/dependabot/pip/vivisect-1.0.3
build(deps): bump vivisect from 1.0.1 to 1.0.3
2021-05-11 18:48:16 +02:00
dependabot[bot]
0f16787ef9 build(deps): bump vivisect from 1.0.1 to 1.0.3
Bumps [vivisect](https://github.com/vivisect/vivisect) from 1.0.1 to 1.0.3.
- [Release notes](https://github.com/vivisect/vivisect/releases)
- [Changelog](https://github.com/vivisect/vivisect/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/vivisect/vivisect/compare/v1.0.1...v1.0.3)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 15:01:03 +00:00
Moritz
495a270c99 Update CHANGELOG.md 2021-05-11 16:32:54 +02:00
Moritz
424a25cb91 Fix tests on Windows - reduced memory impact and general fixes (#545)
* Update tests.yml

* Update .github/workflows/tests.yml

* Update tests.yml

* update

* min tests

* enable all, no sigpaths

* update cache

* save workspace, log caching

* updated tests

* update tests

* update rec call test

* lower cache size

* address Ana's feedback
2021-05-11 16:29:01 +02:00
Capa Bot
fa0809685e Sync capa rules submodule 2021-05-11 11:10:45 +00:00
Ana Maria Martinez Gomez
188966a94b changelog: support multiple authors
GH didn't support multiple authors, producing a breaking entry in the
last update. Correct the entry and mention the fix in the CHANGELOG.

https://github.com/fireeye/capa/issues/555
2021-05-11 12:48:30 +02:00
Capa Bot
d7b7e0111e Sync capa rules submodule 2021-05-10 08:24:40 +00:00
Capa Bot
be11223e4b Sync capa rules submodule 2021-05-07 15:06:52 +00:00
Ana Maria Martinez Gomez
2cbf5147c0 changelog: add #517 and capa/rules/374
Add to the changelog that we now update `New Rules` section in CHANGELOG
automatically.
2021-05-07 17:01:55 +02:00
Capa Bot
5b026df5f4 Sync capa rules submodule 2021-05-07 14:47:03 +00:00
Ana María Martínez Gómez
ac842c95d3 Merge pull request #549 from Ana06/changelog
Update CHANGELOG and release
2021-05-07 16:34:08 +02:00
Capa Bot
aaaeec4de7 Sync capa rules submodule 2021-05-07 13:54:11 +00:00
Capa Bot
99a7380faf Sync capa-testfiles submodule 2021-05-07 12:49:58 +00:00
Ana Maria Martinez Gomez
f43ffabded doc: add item to release checklist
We should update capa everywhere after releasing!
2021-05-07 12:55:02 +02:00
Ana Maria Martinez Gomez
52c0cfd5d0 changelog: prepare to automatize new rules entries
Use an empty item in the `New Rules` section as a marker for the GitHub
Action. If this causes problems, we could look into other solution such
as writing 2 lines before `### Bug Fixes`. But I think this is the
easiest I can come up with. So lets give it a try.
2021-05-07 12:55:02 +02:00
Ana Maria Martinez Gomez
1caf4a7fbf changelog: add missing changes
Add missing changes to CHANGELOG. It should be up-to-date now, with the
exception of the dependencies updates which I think need discussion.
2021-05-07 12:54:59 +02:00
Ana Maria Martinez Gomez
98a976fa72 changelog: add v1.6.3
Add v1.6.3 release which backports IDA 7.6 support to Python 2. Also
remove the capa-rules raw diff as there are not changes (and the tag
doesn't exist).
2021-05-06 23:25:53 +02:00
Capa Bot
3a883807e5 Sync capa rules submodule 2021-05-06 18:07:01 +00:00
Capa Bot
b1b34db0b6 Sync capa rules submodule 2021-05-04 13:43:40 +00:00
Capa Bot
4901cd1da1 Sync capa-testfiles submodule 2021-05-04 07:26:14 +00:00
Capa Bot
272471e158 Sync capa rules submodule 2021-05-03 22:42:41 +00:00
William Ballenthin
8f0ce11ff6 tests: register common FLIRT sigs
closes #538
2021-05-01 08:06:56 -06:00
Willi Ballenthin
e8c807b993 Merge pull request #541 from fireeye/dependabot/pip/black-21.4b2
build(deps-dev): bump black from 21.4b0 to 21.4b2
2021-05-03 08:35:32 -06:00
dependabot[bot]
0b1c80d4d5 build(deps-dev): bump black from 21.4b0 to 21.4b2
Bumps [black](https://github.com/psf/black) from 21.4b0 to 21.4b2.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/master/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-03 06:36:46 +00:00
Capa Bot
82ce223c9b Sync capa-testfiles submodule 2021-04-30 21:06:56 +00:00
Capa Bot
f190b630b7 Sync capa-testfiles submodule 2021-04-30 21:06:48 +00:00
Capa Bot
614a6caee6 Sync capa rules submodule 2021-04-30 21:05:57 +00:00
Capa Bot
ddda87373d Sync capa rules submodule 2021-04-30 20:35:46 +00:00
Capa Bot
9ceebb9bb2 Sync capa-testfiles submodule 2021-04-30 17:13:44 +00:00
Willi Ballenthin
7d2bb6f61b changelog: document FLIRT #446 2021-04-30 08:54:32 -06:00
Willi Ballenthin
c7fe132389 Merge pull request #446 from fireeye/function-id-flirt
feature: match functions with FLIRT
2021-04-30 08:49:30 -06:00
William Ballenthin
404c7a7e88 tests: fix function id tests 2021-04-30 08:48:49 -06:00
William Ballenthin
9a2827935f sigs: add README with license 2021-04-30 08:45:41 -06:00
William Ballenthin
55b83fc2b5 tests: re-enable function id test 2021-04-30 08:37:38 -06:00
William Ballenthin
b89a29b997 freeze: use common args 2021-04-30 08:35:46 -06:00
Moritz
5aa7c57798 Merge pull request #536 from Ana06/ida7_6sp1
doc: document IDA 7.6sp1
2021-04-29 11:05:42 +02:00
Ana Maria Martinez Gomez
e46d1bbbfb doc: document IDA 7.6sp1
The Service Pack 1 for IDA 7.6 includes a bug fix that broke capa
explorer. Document this as an alternative to install the patch.
2021-04-29 11:00:12 +02:00
William Ballenthin
14abb7d4f6 pep8 2021-04-27 13:41:59 -06:00
William Ballenthin
b0c27f5890 setup: bump viv-utils dep v0.6.2 2021-04-27 13:29:45 -06:00
William Ballenthin
bd92933030 show-features: accept signatures or use default 2021-04-27 13:27:59 -06:00
William Ballenthin
249332a9dd lint: load default sigs 2021-04-27 13:22:45 -06:00
William Ballenthin
1a99ff8ccb main: remove old code 2021-04-27 13:12:39 -06:00
William Ballenthin
7373437317 pep8 2021-04-27 13:12:20 -06:00
William Ballenthin
4e7364f25b main: import flirt at top level 2021-04-27 13:11:05 -06:00
William Ballenthin
ce9fd73fa9 main: further document not analyzing workspace 2021-04-27 13:09:52 -06:00
William Ballenthin
9ca1a7ebb6 extractors: do cast-to-int correctly 2021-04-27 13:07:27 -06:00
William Ballenthin
e8457c7abf Merge branch 'function-id-flirt' of github.com:fireeye/capa into function-id-flirt 2021-04-27 12:34:26 -06:00
William Ballenthin
f4ba5a5eb9 setup: bump viv-utils 0.6.1 for more platform support 2021-04-27 12:33:44 -06:00
Moritz Raabe
fc126451a7 add signature files 2021-04-27 19:27:02 +02:00
William Ballenthin
89ad582af5 main: flirt: pat: ensure posix-style line endings 2021-04-27 11:05:21 -06:00
Capa Bot
e66d74764a Sync capa rules submodule 2021-04-27 15:02:51 +00:00
William Ballenthin
4962fcfcde ci: fix accidental merge conflict 2021-04-26 12:19:25 -06:00
William Ballenthin
582e45f72f Merge branch 'function-id-flirt' of github.com:fireeye/capa into function-id-flirt 2021-04-26 12:14:44 -06:00
William Ballenthin
6ec89baf26 pep8 2021-04-26 12:12:51 -06:00
William Ballenthin
76cd530a0f flirt: py3 2021-04-26 12:11:59 -06:00
William Ballenthin
f6a105bcc1 pep8 2021-04-26 12:09:39 -06:00
William Ballenthin
75eed82d33 main: clarify that get_workspace caller is responsible for saving 2021-04-26 12:08:20 -06:00
Capa Bot
fbe307d26a Sync capa rules submodule 2021-04-26 16:20:38 +00:00
Capa Bot
c4a0c3d54a Sync capa rules submodule 2021-04-26 16:18:28 +00:00
William Ballenthin
c79f461e39 Merge branch 'master' into function-id-flirt 2021-04-26 09:47:42 -06:00
Capa Bot
24cd301fa8 Sync capa-testfiles submodule 2021-04-26 14:53:44 +00:00
Willi Ballenthin
a32d609ead Merge pull request #534 from fireeye/dependabot/pip/black-21.4b0
build(deps-dev): bump black from 20.8b1 to 21.4b0
2021-04-26 08:45:10 -06:00
William Ballenthin
a0e045dc52 ci: use black/isort dep from setup.py
closes #535
2021-04-26 08:39:01 -06:00
William Ballenthin
3111593ab8 pep8 2021-04-26 08:34:36 -06:00
Capa Bot
75d9ff5fff Sync capa rules submodule 2021-04-26 12:26:25 +00:00
dependabot[bot]
42877b0b6e build(deps-dev): bump black from 20.8b1 to 21.4b0
Bumps [black](https://github.com/psf/black) from 20.8b1 to 21.4b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/master/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-26 06:30:28 +00:00
Capa Bot
f54b697187 Sync capa rules submodule 2021-04-23 22:50:16 +00:00
Capa Bot
e4a001170c Sync capa-testfiles submodule 2021-04-23 22:49:23 +00:00
Willi Ballenthin
bb15023b0b Merge pull request #533 from fireeye/mr-tz-patch-1
Update installation.md
2021-04-22 14:40:55 -06:00
Moritz
54531ebf35 Update installation.md 2021-04-22 20:41:07 +02:00
Capa Bot
9257e326f3 Sync capa-testfiles submodule 2021-04-22 18:04:58 +00:00
Capa Bot
b59b83a86a Sync capa-testfiles submodule 2021-04-22 17:39:19 +00:00
Capa Bot
caec649a5d Sync capa rules submodule 2021-04-16 14:23:56 +00:00
Capa Bot
09d0286b1b Sync capa rules submodule 2021-04-14 18:35:29 +00:00
Ana María Martínez Gómez
1ebe9766c0 Merge pull request #530 from Ana06/masterv1-6-2
changelog: add v1.6.2
2021-04-14 10:44:57 +02:00
Capa Bot
3e3b1579c3 Sync capa rules submodule 2021-04-14 06:23:30 +00:00
Ana Maria Martinez Gomez
ec6b380acd changelog: add v1.6.2
The code of v1.6.2 is not included in the `master` branch, as it was
backported to `master-py2`. But users may expect to find all releases in
the CHANGELOG of the master branch.
2021-04-13 17:27:48 +02:00
Willi Ballenthin
5ceb515325 Merge pull request #528 from fireeye/williballenthin-patch-2
explorer: readme: document IDA 7.6 patch
2021-04-13 08:54:59 -06:00
Willi Ballenthin
8938744e3e Merge pull request #497 from fireeye/williballenthin-patch-1
ida: support 7.6
2021-04-13 08:54:51 -06:00
Willi Ballenthin
d0f6b47f58 changelog: #528 2021-04-13 08:35:10 -06:00
Willi Ballenthin
a07bcbff2e explorer: readme: document IDA 7.6 patch
closes #496
2021-04-13 08:33:37 -06:00
Moritz
3023634536 build using Py3.8 and test across more OSs (#506)
* build using Py3.8 and test across more OSs

* enable for release

* test builds on push to master
2021-04-13 15:42:58 +02:00
Moritz
a11d04e92b Merge pull request #525 from fireeye/dependabot/pip/smda-1.5.14
build(deps): bump smda from 1.5.13 to 1.5.14
2021-04-12 14:13:36 +02:00
dependabot[bot]
2140a3d762 build(deps): bump smda from 1.5.13 to 1.5.14
Bumps [smda](https://github.com/danielplohmann/smda) from 1.5.13 to 1.5.14.
- [Release notes](https://github.com/danielplohmann/smda/releases)
- [Commits](https://github.com/danielplohmann/smda/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-12 06:32:25 +00:00
Willi Ballenthin
1f6debc6e0 Merge pull request #524 from fireeye/mr-tz-patch-1
Update pull_request_template.md
2021-04-09 15:03:13 -06:00
Moritz
eb5c705083 Update pull_request_template.md 2021-04-09 15:03:43 +02:00
Capa Bot
f01044e453 Sync capa rules submodule 2021-04-09 11:19:42 +00:00
Moritz
8ef3eb85a2 Merge pull request #523 from fireeye/auto-detect-sc-extension-2
move auto format check
2021-04-09 13:16:12 +02:00
Moritz Raabe
d1cd4ef259 move auto format check 2021-04-09 11:59:30 +02:00
Capa Bot
a8bef0d9c0 Sync capa rules submodule 2021-04-09 09:21:00 +00:00
Moritz
309a9abb8a Merge pull request #521 from fireeye/auto-detect-sc-extension
auto detect shellcode file extensions
2021-04-09 11:13:25 +02:00
Moritz
cc13a7681a Merge pull request #522 from fireeye/explorer/update-docs
updating capa explorer doc
2021-04-09 10:31:03 +02:00
Michael Hunhoff
503a723611 updating capa explorer doc 2021-04-08 14:06:23 -06:00
Moritz Raabe
998f4a6bad auto detect shellcode file extensions 2021-04-08 18:49:22 +02:00
Willi Ballenthin
1be3613063 changelog: describe #519 2021-04-08 09:10:14 -06:00
Willi Ballenthin
9ffbe5cd76 Merge pull request #519 from fireeye/dependabot/pip/ruamel-yaml-0.17.4
build(deps): bump ruamel-yaml from 0.17.0 to 0.17.4
2021-04-08 09:06:14 -06:00
Ana María Martínez Gómez
255d6ea176 Merge pull request #517 from Ana06/better-tag
ci: add capa release link to capa-rules tag
2021-04-08 10:49:07 +02:00
dependabot[bot]
628e2ef3f4 build(deps): bump ruamel-yaml from 0.17.0 to 0.17.4
Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.0 to 0.17.4.

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-08 08:49:03 +00:00
Ana María Martínez Gómez
64465a7a31 Merge pull request #480 from Ana06/py3-only 2021-04-08 10:48:15 +02:00
Ana Maria Martinez Gomez
9d79baa96a ci: add capa release link to capa-rules tag
GitHub displays the commit's message of the tag if no description is
given, which is ugly. Use annotated tags which include a message. Use
the release link as message, as this is useful information.
2021-04-07 18:46:51 +02:00
Ana Maria Martinez Gomez
3013269a1c changelog: Update changelog
Add `drop Python 2 support` entry.
2021-04-07 18:24:52 +02:00
Ana Maria Martinez Gomez
bbff3016fe doc: Update Python 2 related documentation
Update documentation and code comments which mention Python 2.
2021-04-07 18:20:08 +02:00
Ana Maria Martinez Gomez
e9d190799e py3: use Python 3.6 to publish capa 2021-04-07 18:20:08 +02:00
Ana Maria Martinez Gomez
0465333aa4 py3: Python 3 knows about cp65001
Python 2 doesn't know about `cp65001`. But Python 3 does. Since Python
3.8 `cp65001` is an alias to `utf_8`. But not before Python 3.8 and it
used to cause some problems:
https://bugs.python.org/issue36778
Keep this code to ensure same behavior for all Python versions.
2021-04-07 18:20:08 +02:00
Ana Maria Martinez Gomez
28406dafa1 py3: codecs.decode doesn't raise TypeError
`codecs.decode` doesn't raise `TypeError` in Python 3. Just obey the
comment!
2021-04-07 18:20:08 +02:00
Ana Maria Martinez Gomez
73a49c6a1f py3: remove rstrip("L") needed in Python 2
In Python 3, long integers are not formatted with a trailing `L`, so
this code is not longer needed.
2021-04-07 18:20:08 +02:00
Ana Maria Martinez Gomez
4028171f59 py3: use python3 in shebang 2021-04-07 18:20:08 +02:00
Ana Maria Martinez Gomez
5d341ba078 py3: remove six
As we are not supporting Python 2 any longer, we can stop using six and
use the equivalent Python 3 method instead.
2021-04-07 18:20:07 +02:00
Ana Maria Martinez Gomez
dfb7cf4888 py3: set and document env
Document how to use env now that we are Python3 only. Adapt
`scripts/ci.sh`.
2021-04-07 18:20:07 +02:00
Ana Maria Martinez Gomez
d640c57e29 py3: Update setup.py
Require Python 3.6+ in setup.py
2021-04-07 18:20:07 +02:00
Ana Maria Martinez Gomez
c0d6468347 py3: Remove Python 2 tests
Tests don't need to support Python 2 any longer. Do not run tests with
Python 2.
2021-04-07 18:20:07 +02:00
Ana Maria Martinez Gomez
058b61b10c py3: prevent that capa is run with Python2
Raise an exception from main if capa is run with Python < 3.6 to avoid
any silly issues reported to GitHub.
2021-04-07 18:20:07 +02:00
Ana Maria Martinez Gomez
aa4d6305af py3: remove py2/3 branches
Remove `if-else`s with a condition like `sys.version_info >= (3, 0)`.
2021-04-07 18:20:06 +02:00
Ana María Martínez Gómez
407ecab162 Merge pull request #515 from Ana06/v1-6-1 2021-04-07 18:03:56 +02:00
Ana Maria Martinez Gomez
cbc1f57b21 changelog: add master (unreleased) to CHANGELOG
Add placeholder for master (unreleased changes) in CHANGELOG. Document
this in the release checklist.
2021-04-07 17:50:19 +02:00
Ana Maria Martinez Gomez
374a9e4337 changelog: v1.6.1
This release includes several bug fixes, such as a vivisect fix for a bug, which caused that capa didn't work on Windows with Python 3. It also adds 17 new rules and a bunch of improvements in the rules and IDA rule generator. We appreciate everyone who opened issues, provided feedback, and contributed code and rules.

This is the very last capa release that supports Python 2.
2021-04-07 17:50:16 +02:00
Capa Bot
83e2f80d10 Sync capa-testfiles submodule 2021-04-07 13:53:32 +00:00
Ana Maria Martinez Gomez
576211c4ef version: bump to v1.6.1 2021-04-07 11:11:43 +02:00
Ana María Martínez Gómez
31fc5a31d6 Merge pull request #513 from Ana06/ping-dependencies
setup: pin dependencies
2021-04-07 10:19:04 +02:00
Ana Maria Martinez Gomez
eb08943d4f setup: pin dependencies
Pin all dependencies in setup to the currently used version to avoid
that a new release breaks capa without being noticed.

Closes https://github.com/fireeye/capa/issues/498
2021-04-07 09:40:13 +02:00
Ana María Martínez Gómez
c36ed71353 Merge pull request #470 from fireeye/ci/test-windows 2021-04-07 09:38:34 +02:00
Ana Maria Martinez Gomez
fa52dbcf84 ci: skip smda tests in win32
Due to a bug, two `test_smda_features` tests are failing:
https://github.com/danielplohmann/smda/issues/20

Disable them until the bug is fixed.
2021-04-06 21:53:22 +02:00
Ana Maria Martinez Gomez
d412e66cea ci: do not test Python 2.7 with Windows
The Python 2.7 tests fail in Windows with vivisect because the Windows
filesystem encoding is not UTF-8. This shouldn't be a problem when using
capa as the given filename most likely uses the same encoding, but we
force UTF-8 in our tests. As we are planing to remove Python 2 support
is not wortwhile to invest time in making this test working. Instead,
test Python 2.7 only in Ubuntu.
2021-04-06 21:39:01 +02:00
Moritz Raabe
efe50d3313 ci: test on Windows and macOS
Run the tests on Windows and macOS to avoid failures OS related.

closes #460
2021-04-06 21:38:07 +02:00
Ana María Martínez Gómez
1062ba995e doc: add milestones link to release checklist
This makes it a bit easier to check if all milestoned issues/PRs are addressed, or reassign to a new milestone.

I am committing directly to master as this is a minor change which doesn't need review.
2021-04-06 10:21:43 +02:00
Ana María Martínez Gómez
7f93bd5b59 Merge pull request #512 from fireeye/williballenthin-patch-2
setup: bump viv to v1.0.1
2021-04-06 10:17:44 +02:00
Willi Ballenthin
275d170680 setup: bump viv to v1.0.1 2021-04-05 21:22:17 -06:00
Moritz
6d7e10b804 Merge pull request #511 from fireeye/ci/fix-typos
fix submodule typos
2021-04-05 13:13:41 +02:00
Moritz Raabe
25944864f7 fix submodule typos 2021-04-05 12:52:08 +02:00
Capa Bot
5e84a16eba Sync capa rules submodule 2021-04-01 16:44:59 +00:00
Capa Bot
244ec163a3 Sync capa-testfiles submodule 2021-04-01 16:44:11 +00:00
Capa Bot
dabd2174d4 Sync capa rules submodule 2021-03-29 16:25:18 +00:00
Moritz
f8d2b41a86 Merge pull request #495 from fireeye/gh/add-pr-template
add PR template
2021-03-29 17:31:05 +02:00
Capa Bot
902972a1ee Sync capa-testfiles submodule 2021-03-29 12:49:24 +00:00
Capa Bot
bddb5fbd2f Sync capa rules submodule 2021-03-26 11:17:46 +00:00
Capa Bot
adfd769963 Sync capa-testfiles submodule 2021-03-26 11:00:35 +00:00
Capa Bot
c75e70ec74 Sync capa-testfiles submodule 2021-03-26 11:00:15 +00:00
Moritz
6118183105 Merge pull request #504 from fireeye/mr-tz-patch-1
Update setup.py
2021-03-26 11:58:52 +01:00
Moritz
da755d8411 Update setup.py 2021-03-26 11:44:04 +01:00
mike-hunhoff
742e03d90f Merge pull request #503 from fireeye/explorer/update-readme
updating capa explorer README
2021-03-25 14:51:21 -06:00
Capa Bot
744228a03e Sync capa rules submodule 2021-03-25 20:48:41 +00:00
Michael Hunhoff
5d1c6f54cd updating capa explorer README 2021-03-25 14:30:28 -06:00
mike-hunhoff
0a3dd4600b Merge pull request #468 from fireeye/features/support-string-values-special-chars
add support for string features with special characters e.g. '\n'
2021-03-25 12:58:00 -06:00
Michael Hunhoff
0289891d07 merging upstream 2021-03-25 12:43:59 -06:00
Michael Hunhoff
87cdf837e6 merging upstream 2021-03-25 12:42:36 -06:00
Capa Bot
ea4c7d6403 Sync capa rules submodule 2021-03-25 18:37:22 +00:00
Capa Bot
2807549564 Sync capa rules submodule 2021-03-25 07:21:21 +00:00
Capa Bot
c0fe96cec6 Sync capa-testfiles submodule 2021-03-25 07:17:41 +00:00
mike-hunhoff
8c967ac237 Merge pull request #500 from fireeye/explorer/improve-rulegen-search
explorer: add checks to validate matched data when searching
2021-03-24 15:55:34 -06:00
Michael Hunhoff
c48b46e932 explorer: adding checks to validate matched data when searching 2021-03-24 15:33:20 -06:00
mike-hunhoff
49d1af7798 improve unit tests for strings containing special characters
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2021-03-24 13:22:18 -06:00
mike-hunhoff
d44fd008ae improve unit tests for strings containing special characters
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2021-03-24 13:22:04 -06:00
Moritz Raabe
c0c9ea3403 incorprate Ana's feedback 2021-03-24 09:22:40 +01:00
Michael Hunhoff
21359da766 updating test for strings with special characaters 2021-03-23 16:02:47 -06:00
Michael Hunhoff
e51c79c241 adding lint for incorrect rule string format, refined rendering for strings 2021-03-23 15:55:48 -06:00
Willi Ballenthin
e22113c20d ida: support 7.6
closes #496
2021-03-23 08:43:33 -06:00
Capa Bot
195bae903f Sync capa rules submodule 2021-03-23 12:25:20 +00:00
Moritz Raabe
5aff21a9a1 add PR template 2021-03-23 10:52:01 +01:00
Ana María Martínez Gómez
6f289d1b8e Merge pull request #476 from Ana06/tag-workflow 2021-03-23 09:54:59 +01:00
Moritz
71b21aec59 Merge pull request #492 from fireeye/ignore-gitfiles
rule loading: ignore files starting with .git
2021-03-23 08:16:29 +01:00
Capa Bot
42a87d4eaa Sync capa-testfiles submodule 2021-03-23 07:14:58 +00:00
Capa Bot
51d125642f Sync capa rules submodule 2021-03-23 07:14:21 +00:00
mike-hunhoff
ddebf2e1cb Merge pull request #493 from fireeye/enhance/472
rule generator: support subscope rules
2021-03-22 17:28:43 -06:00
Michael Hunhoff
7f3e8f1fb1 adding support to match subscope rules and auto insert child statements when creating a new basic block subscope 2021-03-22 17:12:13 -06:00
Ana María Martínez Gómez
ab7dbcd2e4 Merge pull request #491 from fireeye/williballenthin-patch-3 2021-03-22 19:16:49 +01:00
Ana Maria Martinez Gomez
7e5cbddf5d doc: document release process
Add a release checklist.

Closes https://github.com/fireeye/capa/issues/184
2021-03-22 19:14:02 +01:00
Moritz Raabe
44f517c20d rule loading: ignore files starting with .git 2021-03-22 18:11:29 +01:00
Michael Hunhoff
7bf8c6e3a1 merging upstream 2021-03-22 10:33:36 -06:00
Michael Hunhoff
31ea683335 merge upstream 2021-03-22 09:53:07 -06:00
Willi Ballenthin
29d8f1fd27 ci: tests: pin OS version 2021-03-22 09:51:20 -06:00
Willi Ballenthin
a6c472bb2a ci: publish: pin OS version 2021-03-22 09:50:47 -06:00
Willi Ballenthin
b880d419a3 ci: build: pin OS versions 2021-03-22 09:50:04 -06:00
Capa Bot
a2ff87af8a Sync capa rules submodule 2021-03-22 15:45:10 +00:00
Willi Ballenthin
5b9c577380 Merge pull request #489 from fireeye/dependabot/pip/viv-utils-0.6.0
Bump viv-utils from 0.5.0 to 0.6.0
2021-03-22 09:39:52 -06:00
Capa Bot
4775e124db Sync capa rules submodule 2021-03-22 09:02:35 +00:00
Moritz
c243158d7c Merge pull request #486 from fireeye/fix/eol-improvements
EOL improvements
2021-03-22 09:58:29 +01:00
Capa Bot
8afc3f46f6 Sync capa rules submodule 2021-03-22 08:41:21 +00:00
dependabot[bot]
8b5dc54397 Bump viv-utils from 0.5.0 to 0.6.0
Bumps [viv-utils](https://github.com/williballenthin/viv-utils) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/williballenthin/viv-utils/releases)
- [Commits](https://github.com/williballenthin/viv-utils/compare/v0.5.0...v0.6.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-22 06:20:47 +00:00
Capa Bot
1dbb34df9f Sync capa-testfiles submodule 2021-03-21 19:28:58 +00:00
mike-hunhoff
9383f0bc77 Merge pull request #474 from fireeye/explorer/fix-471
explorer: adding support for multi-line tab and SHIFT + Tab
2021-03-19 19:11:14 -06:00
Willi Ballenthin
900a03c172 setup: bump viv-utils version for better FLIRT matching 2021-03-19 11:15:15 -06:00
Moritz Raabe
13306b71e0 add file 2021-03-19 09:40:44 +01:00
Moritz Raabe
8719a23de4 dos2unix 2021-03-19 09:40:44 +01:00
Moritz Raabe
7e0b5236af better deal with CRLF/LF issues 2021-03-19 09:40:43 +01:00
Moritz Raabe
c7798b3254 ensure LF end of line 2021-03-19 09:40:43 +01:00
Willi Ballenthin
7d668550f5 Merge pull request #485 from fireeye/ci/ensure-lf-eol
ensure LF end of line
2021-03-18 14:41:13 -06:00
Capa Bot
c945eaf804 Sync capa rules submodule 2021-03-18 20:41:05 +00:00
Moritz Raabe
1bfe0e0874 ensure LF end of line 2021-03-18 20:15:23 +01:00
Capa Bot
153c6a7b01 Sync capa-testfiles submodule 2021-03-18 18:04:33 +00:00
Ana Maria Martinez Gomez
30a83fa382 doc: Fix broken link in README
Introduced in https://github.com/fireeye/capa/pull/478
2021-03-16 16:37:33 +01:00
Willi Ballenthin
c0bcefe0bf Merge pull request #479 from Ana06/viv-utils5
setup: bump viv-utils to 0.5.0
2021-03-16 07:02:43 -06:00
Ana Maria Martinez Gomez
5d16a77891 ci: tag capa-rules on release
Add GitHub Action to tag capa-rules when releasing capa. The used tag
name is the same as the one in capa.
2021-03-16 12:45:02 +01:00
Ana Maria Martinez Gomez
cd01a01894 setup: bump viv-utils to 0.5.0
In viv-utils `getWorkspace` raises `IncompatibleVivVersion` on Python 3
when `vw.loadWorkspace(viv_file)` raises `UnicodeDecodeError`.

Fixes https://github.com/fireeye/capa/issues/469

As we use the same version in py2 and py3, define the viv-utils
requirement once.
2021-03-16 10:51:50 +01:00
Willi Ballenthin
df36bb9f35 Merge pull request #478 from Ana06/badges
doc: Improve README badges
2021-03-15 14:42:57 -06:00
William Ballenthin
8a3f5e423b setup: bump viv-utils version 2021-03-15 13:39:44 -06:00
William Ballenthin
177605aaf8 flirt: enable only on py3, ignore otherwise 2021-03-15 13:38:29 -06:00
Ana María Martínez Gómez
030893e125 Merge pull request #475 from Ana06/incompatible-viv
changelog: document incompatibility of viv files
2021-03-15 17:30:17 +01:00
Ana Maria Martinez Gomez
b2ab8ab54c doc: Improve README badges
- Add a link to the `PyPI - Python Version` badge. Otherwise it opens
the image when clicking on it, which is inconsistent with the other
labels. I arrived too late to point this out in:
https://github.com/fireeye/capa/pull/477
- Add release badge with last release version. This may help users to
realize that a new version has been released.
- Add downloads badge.
- Order labels by color.

Closes https://github.com/fireeye/capa/issues/196
2021-03-15 16:47:15 +01:00
Willi Ballenthin
12eb1b96de Merge pull request #477 from fireeye/mr-tz-patch-1
Update README.md with Python version badge
2021-03-15 08:35:27 -06:00
Moritz
cff7d4bad4 Update README.md 2021-03-15 11:54:11 +01:00
Ana Maria Martinez Gomez
a31c616a21 changelog: document incompatibility of viv files
`.viv` files (generated by vivisect) are not compatible between Python 2
and Python 3. This causes capa to raise an `UnicodeDecodeError`
exception and should be documented better. I'll add this change to the
release notes after the review.

Related to https://github.com/fireeye/capa/issues/469
2021-03-15 10:26:32 +01:00
Michael Hunhoff
3d2b4dcc26 adding support for multi-line tab and SHIFT + Tab 2021-03-11 17:13:43 -07:00
Michael Hunhoff
c7d24ee290 adding support for string features with special characters e.g. '\n' 2021-03-10 13:56:54 -07:00
mike-hunhoff
06c958f081 Merge pull request #465 from fireeye/explorer/fix-463
explorer: improve settings modification
2021-03-10 11:30:23 -07:00
Michael Hunhoff
b8efe585d5 fix 463, improve settings UI 2021-03-09 14:56:44 -07:00
Willi Ballenthin
e7eb2152cc Merge pull request #464 from fireeye/explorer/fix-462
fix 462
2021-03-09 12:13:54 -07:00
Michael Hunhoff
e1a8641399 fixes 462, default to empty string when accessing rule path stored in ida_settings 2021-03-09 12:09:35 -07:00
Capa Bot
cffac62e68 Sync capa rules submodule 2021-03-09 10:00:48 +00:00
Ana María Martínez Gómez
7a8c0572e9 Merge pull request #455 from Ana06/v1-6-0 2021-03-09 10:48:01 +01:00
Ana Maria Martinez Gomez
5596d5f8b2 version: bump to v1.6.0 2021-03-09 10:36:26 +01:00
Ana Maria Martinez Gomez
06fd02cd61 changelog: v1.6.0
This release adds the capa explorer rule generator plugin for IDA Pro,
vivisect support for Python 3 and 12 new rules. We appreciate everyone
who opened issues, provided feedback, and contributed code and rules.
Thank you also to the vivisect development team (rakuy0, atlas0
fd00m) for the Python 3 support (v1.0.0) and the fixes for Python 2
(v0.2.1). This is the last capa release which supports Python 2. Next
release will be Python 3 only.
2021-03-09 10:36:26 +01:00
Capa Bot
6b9d1047cf Sync capa rules submodule 2021-03-08 19:39:47 +00:00
Ana Maria Martinez Gomez
a7b3fd72ca changelog: v1.5.1 2021-03-08 20:09:31 +01:00
Ana María Martínez Gómez
dd3deb2358 Merge pull request #454 from fireeye/mr-tz-patch-1
setup: bump viv to 0.2.1
2021-03-08 11:36:18 +01:00
Moritz
c99fce3183 setup: bump viv to 0.2.1 2021-03-08 09:07:04 +01:00
William Ballenthin
4db6227d84 ci: build: test exe: run in debug mode to see messages 2021-03-05 15:49:31 -07:00
William Ballenthin
30e1d409dd pyinstaller: package default signatures into standalone exe 2021-03-05 15:46:23 -07:00
William Ballenthin
ff8a6f1d57 main: use default signature set found in source directory 2021-03-05 15:45:56 -07:00
William Ballenthin
9b5d6f8df0 ci: enable test building of standalone exe in CI 2021-03-05 15:35:42 -07:00
William Ballenthin
1e8919c6e6 pep8 2021-03-05 15:27:44 -07:00
William Ballenthin
1ee7b7b856 merge master 2021-03-05 15:23:47 -07:00
Willi Ballenthin
3e55581bf7 Merge pull request #450 from fireeye/feature-refactor-args
refactor common cli argument handling
2021-03-05 15:07:50 -07:00
Willi Ballenthin
dfbe1418d4 Merge pull request #452 from fireeye/feature-py3-pyinstaller
pyinstaller: update for py3/pyinstaller 4.2
2021-03-05 15:06:47 -07:00
William Ballenthin
7671fca373 pep8 2021-03-05 13:27:16 -07:00
William Ballenthin
c01dde3fb2 ci: disable test building of pyinstaller upon push 2021-03-05 13:26:15 -07:00
William Ballenthin
bb17adeda2 pyinstaller: smda: collect capstone shared library 2021-03-05 13:23:15 -07:00
Willi Ballenthin
9f743f1c59 main: fix reference error 2021-03-05 13:19:54 -07:00
William Ballenthin
ee85c929da pyinstaller: install capstone for smda 2021-03-05 12:59:21 -07:00
William Ballenthin
6f9c660082 ci: test pyinstaller CI 2021-03-05 12:55:19 -07:00
William Ballenthin
e02bb7f5a1 pep8 2021-03-05 12:53:50 -07:00
William Ballenthin
9aaaa044da ci: use py3.9 and pyinstaller 4.2 to build standalone binaries 2021-03-05 12:52:38 -07:00
William Ballenthin
54da8444df pyinstaller: update for py3/pyinstaller 4.2
closes #451
2021-03-05 12:40:21 -07:00
William Ballenthin
063e1229bc pep8 2021-03-05 11:10:12 -07:00
William Ballenthin
eacd70329a merge from master, sorry 2021-03-05 11:06:40 -07:00
William Ballenthin
3a1d5d068c scripts: use common argument handler
closes #449
2021-03-05 10:58:40 -07:00
William Ballenthin
f2749d884f main: factor out common cli argument handling
ref #449
2021-03-05 10:57:39 -07:00
William Ballenthin
bdea61f93b scripts: remove old migration script 2021-03-05 10:57:14 -07:00
William Ballenthin
6006e87c5e pep8 2021-03-05 09:40:43 -07:00
William Ballenthin
1e8161b24e setup: bump viv-utils for FLIRT 2021-03-05 09:39:47 -07:00
William Ballenthin
a3e6d1b611 scripts: add helper to show function id matches 2021-03-05 08:38:02 -07:00
William Ballenthin
1a93999cc0 capa: main: factor loading of flirt signatures into its own routine 2021-03-05 08:34:33 -07:00
William Ballenthin
53684adbdd sigs: add license to test files 2021-03-04 18:07:34 -07:00
William Ballenthin
d3caecc551 pep8 2021-03-04 18:06:06 -07:00
William Ballenthin
004ddb3e66 main: load gzip compressed .pat files 2021-03-04 18:04:46 -07:00
William Ballenthin
20894124e6 tests: test FLIRT matching 2021-03-04 15:50:05 -07:00
William Ballenthin
22c4e3b8c2 viv: cleanup flirt changes 2021-03-04 15:46:14 -07:00
William Ballenthin
c2a4629c62 scripts: add cli arguments to specify signatures 2021-03-04 15:04:33 -07:00
William Ballenthin
c0f4fe6867 merge master 2021-03-04 14:59:17 -07:00
William Ballenthin
f2c95568bd main: add FLIRT signature matching configuration 2021-03-04 14:52:22 -07:00
William Ballenthin
358aab85e7 viv: move FLIRT matching into viv-utils 2021-03-04 14:51:40 -07:00
Ana María Martínez Gómez
829274cd5e Merge pull request #421 from Ana06/viv-py3 2021-03-03 21:40:08 +01:00
Ana Maria Martinez Gomez
c522f5094a Use -j option in test_backend_option
Use `-j` option in `test_backend_option` to check the extractor and that
rules have been extracted. This way we don't need to check if a concrete
rule matches, but only that at least a rule matches.
2021-03-03 18:33:20 +01:00
Ana Maria Martinez Gomez
29b6772721 Test backend option
As `get_extractor` returns only vivisect now, `test_main` is not run for
smda. Test that capa works with all backends. It doesn't test that the
backend is actually called.
2021-03-03 17:36:51 +01:00
Ana Maria Martinez Gomez
695b5b50ab Remove va not None check
Instead of checking if `va` is `None in `get_section()` we should avoid
calling this function with `None`. This have been fixed in the following
PR, so this is not longer needed:
https://github.com/fireeye/capa/pull/442
2021-03-03 17:36:51 +01:00
Ana Maria Martinez Gomez
42af7b2d8b Use default backend instead of None
Set the `backend` variable to the default backend by default instead to
`None`. The `backend` variable is needed in Python 2 as `args.backend`
is only set in Python 3. Although the value of the backend variable is
ignored in Python 2, so that the default value is not used.

Co-authored-by: William Ballenthin <william.ballenthin@fireeye.com>
2021-03-03 17:36:51 +01:00
Ana Maria Martinez Gomez
079a9b5204 Remove backend option from Python 2
Do only provide the backend option in Python 3, as there is only one
backend in Python 2. This way we keep the help text simpler.
2021-03-03 17:36:51 +01:00
Ana Maria Martinez Gomez
e5048fd3ac Add missing va parameter to SegmentationViolation
The `envi.SegmentationViolation()` was missing the `va` required
parameter. This has started failing now, because calling
`vw.getSegment(0x4BA190)` for the `tests/data/mimikatz.exe_` produces
different results in Python 2 and Python 3. It returns `None` in Python
3 while the output in Python 2 is:
`(4939776, 16840, '.data', 'mimikatz')`

I have reported the issue to vivisect:
https://github.com/vivisect/vivisect/issues/370
2021-03-03 17:36:51 +01:00
Ana Maria Martinez Gomez
18eaea95fa Fix TypeError exception in Python3
`va` can be None and this causes Python 3 to raise a TypeError
exception. This is caused by the following breaking change in Python3:
> The ordering comparison operators (<, <=, >=, >) raise a TypeError
> exception when the operands don’t have a meaningful natural ordering.

This didn't failed in the previously tried vivisect version (master from
one week ago and not the release). This may have been caused by a bug in
vivisect that has been fixed.
2021-03-03 17:36:51 +01:00
Ana Maria Martinez Gomez
a4a0a56448 Vivisect 1.0.0 released
Vivisect 1.0.0 (Python 3) has been released, so we do not need to link
to my GitHub branch anymore.

https://pypi.org/project/vivisect
2021-03-03 17:36:50 +01:00
Ana Maria Martinez Gomez
40ed2f39a4 Make backend a required parameter in get_extractor
Make the `backend` argument required in the `get_extractor` internal
routine. Specify a backend in the scripts which call this function. Add
a CLI backend option in capa/features/freeze.py as well.
2021-03-03 17:36:50 +01:00
Ana Maria Martinez Gomez
2859b037aa Use constants for backend option
Use constants instead of string literals for the backend option.
2021-03-03 17:36:50 +01:00
Ana Maria Martinez Gomez
bbb7878e0a Enable tests for vivisect in Python3
Now we support vivisect as backend in Python3. We should test it.
2021-03-03 17:36:50 +01:00
Ana Maria Martinez Gomez
fc438866ec Add option to select the backend in Py3
Now we have two working backends in Python3! Add an option to select
which one to use. With this code, vivisect is the default backend, but
this is really easy to change. We could do some analysis to see if smda
performances better than vivisect once the vivisect implementation.
2021-03-03 17:36:50 +01:00
Ana Maria Martinez Gomez
2da2f498a2 Add script to compare vivisect Python 2 vs 3
Compare the performance of vivisect Python 2 vs 3 by counting the number
of feature of each type extracted for every binary in `tests/data`.
Render the ones that perform bad (under a threshold - 98) and the total
performance. Render also the running time per binary for both Python 2 and 3.

From this result, it seems that vivisect behaves properly with Python3.
2021-03-03 17:36:50 +01:00
Ana Maria Martinez Gomez
29dffffe1b Python3 support for vivisect
Vivisect has moved to Python3. Allow to run vivisect with Python3 in
capa.

I am using the following version of vivisect (which includes fixes for
some bugs I have found and some open PRs in vivisect):
https://github.com/Ana06/vivisect/tree/py-3
2021-03-03 17:36:49 +01:00
Capa Bot
1ecaad5413 Sync capa rules submodule 2021-03-02 15:06:24 +00:00
Willi Ballenthin
cd56d672c0 Merge pull request #442 from fireeye/williballenthin-patch-2
viv: ignore empty branch targets
2021-03-01 08:43:26 -07:00
Willi Ballenthin
68aed3c190 insn: better document when branch va may be none 2021-02-28 23:03:08 -07:00
William Ballenthin
f16ecd837e viv: flirt: add more documentation 2021-02-26 05:02:10 -07:00
Willi Ballenthin
68fcc03d5c viv: ignore empty branch targets
but what does this really mean? why would `getBranches` return `None`?

closes #441
2021-02-25 13:34:59 -07:00
William Ballenthin
bfcae0e754 extractors: viv: match flirt signatures [wip] 2021-02-25 12:21:27 -07:00
William Ballenthin
1b2c8880ee capa: extractors: sketch API extension to support function id 2021-02-25 12:20:29 -07:00
Ana Maria Martinez Gomez
fa7d58d01a Add missing va parameter to SegmentationViolation
The `envi.SegmentationViolation()` was missing the `va` required
parameter. This has started failing now, because calling
`vw.getSegment(0x4BA190)` for the `tests/data/mimikatz.exe_` produces
different results in Python 2 and Python 3. It returns `None` in Python
3 while the output in Python 2 is:
`(4939776, 16840, '.data', 'mimikatz')`

I have reported the issue to vivisect:
https://github.com/vivisect/vivisect/issues/370
2021-02-25 11:20:45 +01:00
Ana Maria Martinez Gomez
ec558f377a Fix TypeError exception in Python3
`va` can be None and this causes Python 3 to raise a TypeError
exception. This is caused by the following breaking change in Python3:
> The ordering comparison operators (<, <=, >=, >) raise a TypeError
> exception when the operands don’t have a meaningful natural ordering.

This didn't failed in the previously tried vivisect version (master from
one week ago and not the release). This may have been caused by a bug in
vivisect that has been fixed.
2021-02-25 10:15:49 +01:00
Ana Maria Martinez Gomez
186eba7197 Vivisect 1.0.0 released
Vivisect 1.0.0 (Python 3) has been released, so we do not need to link
to my GitHub branch anymore.

https://pypi.org/project/vivisect
2021-02-25 10:05:04 +01:00
Ana Maria Martinez Gomez
d28ba3c628 Make backend a required parameter in get_extractor
Make the `backend` argument required in the `get_extractor` internal
routine. Specify a backend in the scripts which call this function. Add
a CLI backend option in capa/features/freeze.py as well.
2021-02-25 10:04:19 +01:00
Ana Maria Martinez Gomez
a026cb84d1 Use constants for backend option
Use constants instead of string literals for the backend option.
2021-02-25 09:35:40 +01:00
Ana Maria Martinez Gomez
3acc3eeabd Enable tests for vivisect in Python3
Now we support vivisect as backend in Python3. We should test it.
2021-02-25 09:35:40 +01:00
Ana Maria Martinez Gomez
a92d2af7f8 Add option to select the backend in Py3
Now we have two working backends in Python3! Add an option to select
which one to use. With this code, vivisect is the default backend, but
this is really easy to change. We could do some analysis to see if smda
performances better than vivisect once the vivisect implementation.
2021-02-25 09:35:40 +01:00
Ana Maria Martinez Gomez
adcb683458 Add script to compare vivisect Python 2 vs 3
Compare the performance of vivisect Python 2 vs 3 by counting the number
of feature of each type extracted for every binary in `tests/data`.
Render the ones that perform bad (under a threshold - 98) and the total
performance. Render also the running time per binary for both Python 2 and 3.

From this result, it seems that vivisect behaves properly with Python3.
2021-02-25 09:35:40 +01:00
Capa Bot
939b29bf60 Sync capa rules submodule 2021-02-24 23:00:34 +00:00
Ana Maria Martinez Gomez
e4925613b3 Python3 support for vivisect
Vivisect has moved to Python3. Allow to run vivisect with Python3 in
capa.

I am using the following version of vivisect (which includes fixes for
some bugs I have found and some open PRs in vivisect):
https://github.com/Ana06/vivisect/tree/py-3
2021-02-24 17:55:39 +01:00
Capa Bot
2f6a6e4628 Sync capa rules submodule 2021-02-24 08:07:52 +00:00
Capa Bot
7938ea34d0 Sync capa rules submodule 2021-02-24 08:06:30 +00:00
Capa Bot
ed94e36f7a Sync capa rules submodule 2021-02-24 00:12:19 +00:00
mike-hunhoff
1c3a8df136 Merge pull request #439 from fireeye/explorer/rulegen-support-file-scope
adding file scope support to rule generator IDA plugin
2021-02-23 11:50:54 -07:00
Michael Hunhoff
9f254b22ee adding file scope support to rule generator IDA plugin 2021-02-23 11:10:34 -07:00
Capa Bot
753f8ce84e Sync capa rules submodule 2021-02-23 17:33:38 +00:00
Capa Bot
acf3b549de Sync capa rules submodule 2021-02-23 15:29:20 +00:00
Capa Bot
669f6dcf98 Sync capa rules submodule 2021-02-23 15:23:19 +00:00
Capa Bot
e4f7c4aab1 Sync capa rules submodule 2021-02-23 15:22:43 +00:00
Moritz
5836d55e21 Merge pull request #438 from fireeye/explorer/show-results-by-function
explorer: adding option to show results by function
2021-02-22 18:23:44 +01:00
Michael Hunhoff
e17bf1a1f4 explorer: adding option to show results by function 2021-02-22 08:16:18 -07:00
Willi Ballenthin
acb253ae9c Merge pull request #437 from fireeye/scripts/show-capabilities
update to support running in IDA w/ Python 3
2021-02-19 17:02:53 -07:00
Michael Hunhoff
cc0aaa301f update to support running in IDA w/ Python 3 2021-02-19 14:28:20 -07:00
mike-hunhoff
4256316045 Merge pull request #436 from fireeye/fix/ida/unmapped-data-ref
check for unmapped addresses when resolving data references
2021-02-19 12:58:16 -07:00
Capa Bot
78ab0c9400 Sync capa-testfiles submodule 2021-02-19 19:39:18 +00:00
Capa Bot
944a670af0 Sync capa rules submodule 2021-02-19 17:17:33 +00:00
Michael Hunhoff
e4e517b334 checked for unmapped address when resolving data references 2021-02-19 10:07:23 -07:00
Capa Bot
ccd7f1ee4b Sync capa-testfiles submodule 2021-02-19 09:54:02 +00:00
Capa Bot
9db7ed88aa Sync capa rules submodule 2021-02-18 21:36:08 +00:00
Capa Bot
a5e7497f56 Sync capa-testfiles submodule 2021-02-18 21:35:02 +00:00
Capa Bot
754f302493 Sync capa rules submodule 2021-02-18 17:56:06 +00:00
Moritz
7783543153 Merge pull request #429 from fireeye/scripts/multiple-backends-show-features
mirror show-capabilities-by-function to enable multiple backends
2021-02-18 09:33:36 +01:00
Moritz
b02f92b3ea Merge pull request #428 from fireeye/linter/ntoskrnl-ntdll-overlap
linter: adding ntoskrnl, ntdll overlap lint
2021-02-18 09:23:02 +01:00
Michael Hunhoff
47b3ef29be removing viv dep from show-capabilities-by-function.py 2021-02-17 14:49:52 -07:00
Michael Hunhoff
1eb615f97c mirror show-capabilities-by-function to enable multiple backends 2021-02-17 14:40:33 -07:00
mike-hunhoff
cfa904a0a0 Merge pull request #426 from fireeye/explorer/rule-generator
initial commit of capa explorer rule generator plugin for IDA Pro
2021-02-17 13:44:54 -07:00
Michael Hunhoff
2d34458d10 linter: adding ntoskrnl, ntdll overlap lint 2021-02-17 13:29:36 -07:00
Capa Bot
e39713c4fd Sync capa rules submodule 2021-02-17 17:10:12 +00:00
Capa Bot
320b734da8 Sync capa rules submodule 2021-02-17 17:00:43 +00:00
Capa Bot
887848625c Sync capa-testfiles submodule 2021-02-17 16:52:43 +00:00
Capa Bot
685f06582d Sync capa rules submodule 2021-02-17 15:18:16 +00:00
Capa Bot
a3c21dba32 Sync capa rules submodule 2021-02-17 14:59:46 +00:00
Capa Bot
9744cde8aa Sync capa rules submodule 2021-02-17 07:27:24 +00:00
Capa Bot
0ba8c9ec00 Sync capa-testfiles submodule 2021-02-16 23:44:50 +00:00
Capa Bot
0764c603b4 Sync capa-testfiles submodule 2021-02-16 23:32:23 +00:00
mike-hunhoff
2d4f7a6946 Update README.md 2021-02-12 14:38:11 -07:00
mike-hunhoff
5346eec84d Update README.md 2021-02-12 14:35:34 -07:00
Michael Hunhoff
b704dd967b updating README related to capa explorer 2021-02-12 14:32:08 -07:00
Michael Hunhoff
84ace24b35 merging upstream 2021-02-12 14:19:23 -07:00
Michael Hunhoff
ea42f76cff updating README related to capa explorer 2021-02-12 14:18:30 -07:00
Michael Hunhoff
dd147dd040 format fixes, strip strings before display 2021-02-12 12:03:48 -07:00
Capa Bot
9a79136d15 Sync capa-testfiles submodule 2021-02-11 15:19:46 +00:00
Capa Bot
b722dd016a Sync capa rules submodule 2021-02-11 07:39:06 +00:00
Capa Bot
054853dc06 Sync capa-testfiles submodule 2021-02-11 07:36:27 +00:00
Capa Bot
e5ceef52c6 Sync capa rules submodule 2021-02-10 16:11:34 +00:00
Capa Bot
92747e8efc Sync capa-testfiles submodule 2021-02-10 14:11:34 +00:00
Capa Bot
6171de54f9 Sync capa-testfiles submodule 2021-02-10 14:05:17 +00:00
Capa Bot
287ef31081 Sync capa rules submodule 2021-02-10 13:44:47 +00:00
Willi Ballenthin
8121f291c3 version: bump to v1.5.1 2021-02-09 09:20:03 -07:00
Moritz
b721b5fcff Merge pull request #420 from fireeye/williballenthin-patch-2
setup: pin viv-utils version
2021-02-09 16:49:11 +01:00
Willi Ballenthin
521dfe0337 setup: bump viv-utils to 0.3.19 2021-02-09 08:18:17 -07:00
Capa Bot
7dc78b7837 Sync capa rules submodule 2021-02-09 15:17:09 +00:00
Michael Hunhoff
1a804ed97b merge upstream 2021-02-09 07:55:53 -07:00
Capa Bot
6636b9d56c Sync capa-testfiles submodule 2021-02-09 12:56:48 +00:00
Capa Bot
325c6cc805 Sync capa rules submodule 2021-02-09 09:58:41 +00:00
Capa Bot
6a6e205973 Sync capa-testfiles submodule 2021-02-08 19:07:40 +00:00
Capa Bot
46ec25d286 Sync capa rules submodule 2021-02-08 17:49:32 +00:00
Capa Bot
6e33a22676 Sync capa rules submodule 2021-02-08 17:48:52 +00:00
Capa Bot
6e81de9e44 Sync capa rules submodule 2021-02-08 17:45:01 +00:00
Willi Ballenthin
03f7bbc3a5 setup: pin viv-utils version 2021-02-08 10:30:31 -07:00
Willi Ballenthin
4354bc9108 Merge pull request #415 from fireeye/williballenthin-patch-2
v1.5.0
2021-02-08 09:55:43 -07:00
Willi Ballenthin
b8fcc2ff0c Merge pull request #417 from fireeye/smda/calls-from-no-api
remove apirefs from calls from
2021-02-08 09:54:04 -07:00
Moritz Raabe
55b7ae10a7 remove apirefs from calls from
closes #416
2021-02-08 11:56:01 +01:00
Willi Ballenthin
6d2a6c98d1 changelog: v1.5.0 2021-02-05 10:59:30 -07:00
Capa Bot
05998b5d05 Sync capa-testfiles submodule 2021-02-04 08:19:32 +00:00
Capa Bot
1063f3fcda Sync capa rules submodule 2021-02-03 18:13:29 +00:00
Capa Bot
93c5e4637b Sync capa rules submodule 2021-02-03 15:15:51 +00:00
Moritz
073c2b5754 Merge pull request #412 from fireeye/ida/meta-add-baseaddr
add imagebase to IDA meta data
2021-02-02 16:48:22 +01:00
mike-hunhoff
ef41d74b82 Merge pull request #411 from fireeye/fix/410
fixes #410
2021-02-02 08:38:23 -07:00
Moritz Raabe
84b3f38810 add imagebase to IDA meta data 2021-02-02 13:54:46 +01:00
mike-hunhoff
2288f38a11 Update capa/main.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2021-02-01 12:45:36 -07:00
mike-hunhoff
dbc4e06657 Update capa/main.py
Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com>
2021-02-01 12:45:29 -07:00
Michael Hunhoff
2433777a76 fixes #410 2021-02-01 11:43:24 -07:00
Moritz
bb7001f5f2 Merge pull request #409 from fireeye/fix/extract-bytes
improve bytes feature extraction
2021-02-01 17:38:40 +01:00
Moritz Raabe
9b5aaa40de improve bytes feature extraction 2021-02-01 17:17:22 +01:00
Capa Bot
96d74f48f4 Sync capa rules submodule 2021-02-01 11:55:33 +00:00
Michael Hunhoff
c8a99c247c rulegen python2.x support 2021-01-29 12:45:04 -07:00
Michael Hunhoff
9f50a37e40 rulegen filtering basic blocks, adding support for double-click to add feature 2021-01-29 11:47:58 -07:00
Michael Hunhoff
54c9e39654 rulegen reorder context menu actions 2021-01-29 11:11:41 -07:00
Michael Hunhoff
3386a1e9f9 rulegen adding vert and hort splitters, moving save button to right 2021-01-29 10:51:26 -07:00
Michael Hunhoff
b413f2eafe rulegen adding support for sync between editor and preview windows 2021-01-28 17:15:18 -07:00
Capa Bot
f07af25a6a Sync capa rules submodule 2021-01-28 16:52:21 +00:00
Willi Ballenthin
14e65c4601 Merge pull request #401 from fireeye/linter-format
Lint rule formatting and improved rule dump
2021-01-28 09:18:20 -07:00
Capa Bot
b5c2fb0259 Sync capa rules submodule 2021-01-28 16:06:09 +00:00
Capa Bot
92d98db7bb Sync capa-testfiles submodule 2021-01-28 15:25:17 +00:00
Michael Hunhoff
9caafedb8d merging upstream 2021-01-28 08:14:16 -07:00
Moritz
e6f7ef604a Merge pull request #404 from fireeye/bugfix/403
fixing #403
2021-01-28 11:17:39 +01:00
Moritz Raabe
0eb8d3e47c fix time debug output 2021-01-28 11:09:25 +01:00
Moritz Raabe
072e30498b adjust negative hex numbers in to_yaml 2021-01-28 10:54:17 +01:00
Moritz Raabe
d6e73577af dont change quotes when dumping 2021-01-28 10:54:17 +01:00
Moritz Raabe
a81f98be8e manual adjust negative numbers 2021-01-28 10:54:17 +01:00
Moritz Raabe
0980e35c29 simplify string comparison 2021-01-28 10:54:17 +01:00
Moritz Raabe
336c2a3aff add option to only check reformat status 2021-01-28 10:54:17 +01:00
Moritz Raabe
e3055bc740 check rule format consistency 2021-01-28 10:54:17 +01:00
Capa Bot
9406e3dbfb Sync capa rules submodule 2021-01-28 09:52:43 +00:00
Moritz
5307b7e1b1 Merge pull request #408 from fireeye/fix/lint-lib-path
adjust expected lib path and log time
2021-01-28 10:28:30 +01:00
Moritz Raabe
f18a8f5b31 adjust expected lib path and log time 2021-01-28 10:18:03 +01:00
Moritz
cfe99c4b72 Merge pull request #407 from fireeye/fix/lint-logging
disable extractor progress
2021-01-28 09:25:07 +01:00
Moritz Raabe
0d439c0f55 disable extractor progress 2021-01-28 09:22:15 +01:00
Moritz
6288a96a8b Merge pull request #406 from fireeye/ci/disable-python36
Disable Python 3.6 tests
2021-01-28 08:35:42 +01:00
Moritz
819b6f6ccf Merge pull request #402 from fireeye/lib-rules-subscoped
potential fix for #398
2021-01-28 08:35:28 +01:00
Moritz Raabe
4bc06aa8cd closes #405 2021-01-28 08:23:15 +01:00
Moritz Raabe
7b64425c24 update doc and test case 2021-01-28 08:18:23 +01:00
Michael Hunhoff
44c9d6a22b fixing #403 2021-01-27 18:29:53 -07:00
Moritz Raabe
c750447d62 potential fix for #398 2021-01-27 17:59:56 +01:00
Michael Hunhoff
b1c99d82fd rulegen adding special handling for count description 2021-01-22 09:41:17 -07:00
Michael Hunhoff
10db79f636 rulegen changes for backwards compat w/ Python 2.x 2021-01-22 08:22:37 -07:00
Willi Ballenthin
059ec8f3f2 Merge pull request #400 from fireeye/ci/enable-py39-2
bump smda, enable Python 3.9
2021-01-22 07:18:54 -07:00
Moritz Raabe
2c5508febd bump smda, enable Python 3.9 2021-01-22 10:00:25 +01:00
Capa Bot
905fff041b Sync capa rules submodule 2021-01-21 21:32:42 +00:00
Michael Hunhoff
cd27a64f4e rulegen clear ruleset cache when user configures new directory 2021-01-21 14:15:52 -07:00
Michael Hunhoff
d1b7a5c2e4 rulegen fixing bug in handling of subscope-rules 2021-01-21 14:05:24 -07:00
Michael Hunhoff
4b81b086db rulegen removing uneeded file 2021-01-21 10:19:37 -07:00
Michael Hunhoff
0db42c28a7 rulegen adding support to use cached ruleset, user click reset to reload rules from disk 2021-01-21 10:09:43 -07:00
Michael Hunhoff
0eca6ce2e3 rulegen adding save button, reducing menu complexity 2021-01-21 09:29:10 -07:00
Michael Hunhoff
34685bf80e rulegen adding header comment to generated rules 2021-01-20 15:22:56 -07:00
Michael Hunhoff
271dc2a6a9 rulegen add ability to configure default values for rule author and scope 2021-01-20 15:12:44 -07:00
Michael Hunhoff
bf0376f73f rulegen adding auto check if new rule matches current function 2021-01-20 14:31:48 -07:00
Michael Hunhoff
cf8656eb2d adding search bar for feature tree in rule generator 2021-01-19 12:03:15 -07:00
Willi Ballenthin
20ce29b033 Merge pull request #396 from fireeye/dependabot/pip/smda-1.5.11
Bump smda from 1.5.10 to 1.5.11
2021-01-19 08:21:00 -07:00
Capa Bot
4bd93a680e Sync capa-testfiles submodule 2021-01-18 08:02:29 +00:00
dependabot[bot]
c9bf7f424d Bump smda from 1.5.10 to 1.5.11
Bumps [smda](https://github.com/danielplohmann/smda) from 1.5.10 to 1.5.11.
- [Release notes](https://github.com/danielplohmann/smda/releases)
- [Commits](https://github.com/danielplohmann/smda/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-01-18 06:44:33 +00:00
Capa Bot
4cde2e1a78 Sync capa rules submodule 2021-01-16 15:39:09 +00:00
Michael Hunhoff
15625b5f8c capa explorer rulegen -> adding styling; adding support for descriptions 2021-01-15 12:52:52 -07:00
Michael Hunhoff
e5f9da1f2b adding submenus to rulegen editor; empty expressions auto pruned from rulegen editor 2021-01-14 16:22:56 -07:00
Michael Hunhoff
ab33c46c87 init commit capa explorer rulegen 2021-01-14 15:46:24 -07:00
Capa Bot
48c045d381 Sync capa rules submodule 2021-01-12 18:30:44 +00:00
Capa Bot
2b385ead7f Sync capa rules submodule 2021-01-12 18:30:11 +00:00
Capa Bot
0fcc9f3df6 Sync capa-testfiles submodule 2021-01-12 18:27:32 +00:00
Capa Bot
b251202804 Sync capa-testfiles submodule 2021-01-12 18:27:11 +00:00
Capa Bot
6967010281 Sync capa-testfiles submodule 2021-01-12 18:26:12 +00:00
Capa Bot
7e0846e66a Sync capa rules submodule 2021-01-12 17:55:13 +00:00
Moritz
4e3daad96d Merge pull request #391 from fireeye/fix/freeze-base-addr
add base address to freeze
2021-01-11 11:30:29 +01:00
Capa Bot
37fb3da5db Sync capa rules submodule 2021-01-08 16:36:36 +00:00
Capa Bot
762f48957c Sync capa rules submodule 2021-01-08 15:16:32 +00:00
Capa Bot
c1af7b8783 Sync capa-testfiles submodule 2021-01-08 15:14:26 +00:00
Moritz Raabe
f89084677d add base address to freeze 2021-01-08 14:48:26 +01:00
Capa Bot
0716084bbb Sync capa-testfiles submodule 2021-01-08 08:46:53 +00:00
Capa Bot
a6c946e6c9 Sync capa rules submodule 2021-01-07 13:59:20 +00:00
Capa Bot
3f6e088faa Sync capa-testfiles submodule 2021-01-07 11:53:24 +00:00
Capa Bot
9abdd5813b Sync capa rules submodule 2021-01-07 07:47:28 +00:00
Capa Bot
f33ea36e6f Sync capa rules submodule 2021-01-05 15:49:04 +00:00
Moritz
8788e0a9c9 Merge pull request #388 from fireeye/ci/linter-update
lint with tags
2021-01-05 16:37:21 +01:00
Moritz Raabe
b1c1cb4b9b lint with --tag 2021-01-05 16:16:35 +01:00
Capa Bot
982d4ac472 Sync capa-testfiles submodule 2021-01-04 14:42:43 +00:00
Capa Bot
b7a8d667b9 Sync capa rules submodule 2021-01-04 12:51:43 +00:00
Capa Bot
8f8729df05 Sync capa-testfiles submodule 2020-12-30 19:06:28 +00:00
Capa Bot
e928d281dd Sync capa-testfiles submodule 2020-12-30 15:21:36 +00:00
Capa Bot
625583f5ab Sync capa rules submodule 2020-12-23 12:44:25 +00:00
Capa Bot
ab54553dd2 Sync capa rules submodule 2020-12-22 17:16:54 +00:00
Moritz
47bf7b1325 Merge pull request #375 from doomedraven/return_dict
add render to dict, is the same as default but just in dictionary so …
2020-12-22 15:52:50 +01:00
Moritz
145d75f579 Merge pull request #381 from fireeye/fix/viv-set-logger-levels
set level of more viv loggers explicitly
2020-12-22 15:52:05 +01:00
Capa Bot
01d976d7f7 Sync capa rules submodule 2020-12-22 13:17:37 +00:00
Capa Bot
095e3720ab Sync capa-testfiles submodule 2020-12-22 12:00:35 +00:00
Capa Bot
d62a37fe1f Sync capa-testfiles submodule 2020-12-21 16:17:33 +00:00
Capa Bot
5323f2fc31 Sync capa rules submodule 2020-12-17 17:14:43 +00:00
Capa Bot
5539cb0d08 Sync capa rules submodule 2020-12-17 17:12:21 +00:00
Capa Bot
76e80106d6 Sync capa-testfiles submodule 2020-12-17 09:29:56 +00:00
Capa Bot
9ab7b9a033 Sync capa rules submodule 2020-12-16 20:47:34 +00:00
Capa Bot
fe97d6a349 Sync capa-testfiles submodule 2020-12-15 19:23:15 +00:00
Capa Bot
2242c2afe8 Sync capa-testfiles submodule 2020-12-15 19:19:09 +00:00
Willi Ballenthin
ec25fb5c36 Merge pull request #384 from fireeye/dependabot/pip/smda-1.5.10
Bump smda from 1.5.9 to 1.5.10
2020-12-14 10:32:31 -07:00
dependabot[bot]
ce25f5cadd Bump smda from 1.5.9 to 1.5.10
Bumps [smda](https://github.com/danielplohmann/smda) from 1.5.9 to 1.5.10.
- [Release notes](https://github.com/danielplohmann/smda/releases)
- [Commits](https://github.com/danielplohmann/smda/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-14 07:15:58 +00:00
Capa Bot
1099f40f19 Sync capa rules submodule 2020-12-12 05:43:31 +00:00
Capa Bot
70368b3f1e Sync capa rules submodule 2020-12-11 10:42:16 +00:00
Capa Bot
0181ebad45 Sync capa-testfiles submodule 2020-12-10 17:38:00 +00:00
DoomedRaven
e158e3f13c remove type hint to make CI happy 2020-12-08 21:46:39 +01:00
DoomedRaven
b1bbded23c black -l 120 . 2020-12-08 21:39:50 +01:00
DoomedRaven
b77d9d3738 isort --profile black --length-sort --line-width 120 capa_as_library.py 2020-12-08 21:34:42 +01:00
DoomedRaven
d0b2421752 isort capa_as_library.py 2020-12-08 20:53:26 +01:00
DoomedRaven
96b65a7c60 add example how to render it as library
```
>>> from capa_as_library import capa_details
>>> details = capa_details("/opt/CAPEv2/storage/analyses/83/binary", "dictionary")
>>> from pprint import pprint as pp
>>> pp(details)
{'ATTCK': {'DEFENSE EVASION': ['Obfuscated Files or Information [T1027]',
                               'Virtualization/Sandbox Evasion::System Checks '
                               '[T1497.001]'],
           'EXECUTION': ['Shared Modules [T1129]']},
 'CAPABILITY': {'anti-analysis/anti-vm/vm-detection': ['execute anti-VM '
                                                       'instructions (3 '
                                                       'matches)'],
                'anti-analysis/obfuscation/string/stackstring': ['contain '
                                                                 'obfuscated '
                                                                 'stackstrings'],
                'data-manipulation/encryption/rc4': ['encrypt data using RC4 '
                                                     'PRGA'],
                'executable/pe/section/rsrc': ['contain a resource (.rsrc) '
                                               'section'],
                'host-interaction/cli': ['accept command line arguments'],
                'host-interaction/environment-variable': ['query environment '
                                                          'variable'],
                'host-interaction/file-system/read': ['read .ini file',
                                                      'read file'],
                'host-interaction/file-system/write': ['write file (3 '
                                                       'matches)'],
                'host-interaction/process': ['get thread local storage value '
                                             '(3 matches)',
                                             'set thread local storage value '
                                             '(2 matches)'],
                'host-interaction/process/terminate': ['terminate process (3 '
                                                       'matches)'],
                'host-interaction/thread/terminate': ['terminate thread'],
                'linking/runtime-linking': ['link function at runtime (7 '
                                            'matches)',
                                            'link many functions at runtime'],
                'load-code/pe': ['parse PE header (3 matches)']},
 'MBC': {'ANTI-BEHAVIORAL ANALYSIS': ['Virtual Machine Detection::Instruction '
                                      'Testing [B0009.029]'],
         'ANTI-STATIC ANALYSIS': ['Disassembler Evasion::Argument Obfuscation '
                                  '[B0012.001]'],
         'CRYPTOGRAPHY': ['Encrypt Data::RC4 [C0027.009]',
                          'Generate Pseudo-random Sequence::RC4 PRGA '
                          '[C0021.004]']},
 'md5': 'ad56c384476a81faef9aebd60b2f4623',
 'path': '/opt/CAPEv2/storage/analyses/83/binary',
 'sha1': 'aa027d89f5d3f991ad3e14ffb681616a77621836',
 'sha256': '16995e059eb47de0b58a95ce2c3d863d964a7a16064d4298cee9db1de266e68d'}
>>>
```
2020-12-08 20:00:24 +01:00
Willi Ballenthin
177c90093e Merge pull request #380 from doomedraven/patch-1
fix is_ordinal IndexError
2020-12-08 09:21:53 -07:00
Moritz Raabe
28ee091107 set level of more viv loggers explicitly 2020-12-08 16:30:23 +01:00
doomedraven
64c71d8e6d fix is_ordinal IndexError
```
 Traceback (most recent call last):
   File "/opt/CAPE/utils/../lib/cuckoo/common/cape_utils.py", line 223, in flare_capa_details
     capabilities, counts = capa.main.find_capabilities(rules, extractor, disable_progress=True)
   File "/usr/local/lib/python2.7/dist-packages/capa/main.py", line 116, in find_capabilities
     function_matches, bb_matches, feature_count = find_function_capabilities(ruleset, extractor, f)
   File "/usr/local/lib/python2.7/dist-packages/capa/main.py", line 68, in find_function_capabilities
     for feature, va in extractor.extract_insn_features(f, bb, insn):
   File "/usr/local/lib/python2.7/dist-packages/capa/features/extractors/viv/__init__.py", line 84, in extract_insn_features
     for feature, va in capa.features.extractors.viv.insn.extract_features(f, bb, insn):
   File "/usr/local/lib/python2.7/dist-packages/capa/features/extractors/viv/insn.py", line 599, in extract_features
     for feature, va in insn_handler(f, bb, insn):
   File "/usr/local/lib/python2.7/dist-packages/capa/features/extractors/viv/insn.py", line 93, in extract_insn_api_features
     for name in capa.features.extractors.helpers.generate_symbols(dll, symbol):
   File "/usr/local/lib/python2.7/dist-packages/capa/features/extractors/helpers.py", line 61, in generate_symbols
     if not is_ordinal(symbol):
   File "/usr/local/lib/python2.7/dist-packages/capa/features/extractors/helpers.py", line 45, in is_ordinal
     return symbol[0] == "#"
 IndexError: string index out of range
```
2020-12-08 09:50:00 +01:00
Moritz
9ce0c94e17 Merge pull request #379 from fireeye/fix/nzxor-xor-instructions
add more xor instructions
2020-12-08 09:37:35 +01:00
Moritz Raabe
08c3372635 add more xor instructions 2020-12-08 09:21:50 +01:00
Capa Bot
2fafc70b69 Sync capa-testfiles submodule 2020-12-07 18:06:53 +00:00
Capa Bot
0e62ebe3a2 Sync capa-testfiles submodule 2020-12-07 17:16:01 +00:00
Moritz
1cc4d20b89 Merge pull request #373 from fireeye/ci/setup-dependabot
add dependabot config
2020-12-07 18:03:57 +01:00
Capa Bot
af4889894a Sync capa rules submodule 2020-12-04 08:31:42 +00:00
Moritz
429a5e1ea3 Merge pull request #378 from fireeye/fix/viv-string-extractor
fix: add viv extract strings for i386ImmMemOper operands
2020-12-04 08:55:23 +01:00
Moritz Raabe
4ef860eb07 fix: add viv extract strings for i386ImmMemOper operands 2020-12-03 20:24:29 +01:00
Capa Bot
b59ebf30c6 Sync capa-testfiles submodule 2020-12-03 18:57:45 +00:00
Capa Bot
a1ae8d54a6 Sync capa rules submodule 2020-12-02 15:24:15 +00:00
Capa Bot
8155207bea Sync capa rules submodule 2020-12-02 15:13:30 +00:00
Capa Bot
337d2cfa6d Sync capa rules submodule 2020-12-02 15:12:27 +00:00
Capa Bot
df2229782b Sync capa rules submodule 2020-12-02 15:08:55 +00:00
doomedraven
5920552649 small improvements 2020-12-01 20:31:56 +01:00
doomedraven
b4827fcb00 add render to dict, is the same as default but just in dictionary so simplifies the integrations 2020-12-01 19:43:54 +01:00
Willi Ballenthin
63983ccb65 Merge pull request #372 from doomedraven/patch-1
Simple example how to use capa as library
2020-12-01 06:56:44 -07:00
Willi Ballenthin
eac7e2b749 capa_as_library: style and comments 2020-12-01 06:54:55 -07:00
Moritz Raabe
65a365bca1 update halo requirements py2/3 2020-12-01 11:46:53 +01:00
Moritz Raabe
fecd0e11eb add dependabot config 2020-12-01 11:46:14 +01:00
doomedraven
51ad526cfc Simple example how to use capa as library
Just quick example how to use capa as library, to save time to someone, reading code and scripts
2020-12-01 11:20:49 +01:00
Moritz
10a062017d Merge pull request #370 from fireeye/pin-smda
pin smda
2020-12-01 11:10:23 +01:00
Moritz Raabe
0d351794db pin smda
addresses #369
2020-12-01 11:02:36 +01:00
Capa Bot
067e3ffced Sync capa-testfiles submodule 2020-11-30 19:36:59 +00:00
Capa Bot
50d55fae56 Sync capa-testfiles submodule 2020-11-23 17:55:56 +00:00
Capa Bot
ce63628d3d Sync capa rules submodule 2020-11-19 15:43:59 +00:00
Capa Bot
13df7f90f6 Sync capa rules submodule 2020-11-19 15:09:24 +00:00
Capa Bot
f5099b873d Sync capa rules submodule 2020-11-19 11:40:38 +00:00
Capa Bot
70eb38895d Sync capa-testfiles submodule 2020-11-18 16:28:34 +00:00
Capa Bot
7aea9fa1d2 Sync capa rules submodule 2020-11-16 19:38:02 +00:00
Capa Bot
5d30be31e0 Sync capa rules submodule 2020-11-16 09:44:08 +00:00
Capa Bot
7abe66e3de Sync capa rules submodule 2020-11-16 06:40:23 +00:00
mike-hunhoff
49ef5e5e64 Merge pull request #364 from fireeye/viv/fix-353
improve viv extractor unicode string detection
2020-11-10 17:56:47 -07:00
Michael Hunhoff
c2266bc105 improve viv extractor unicode string detection with supporting unit test 2020-11-10 12:23:07 -07:00
Moritz
a813e219e6 Merge pull request #363 from fireeye/williballenthin-patch-1
ci: disable py3.9 testing
2020-11-09 21:14:36 +01:00
Moritz
1c1fb20546 Merge pull request #355 from danielplohmann/backend-smda
initial commit for backend-smda
2020-11-09 21:13:51 +01:00
Willi Ballenthin
65feb60bb8 ci: disable py3.9 testing 2020-11-09 13:06:37 -07:00
Daniel Plohmann (jupiter)
f7492c7dc7 throw UnsupportedRuntimeError if SmdaFeatureExtractor is used with a Python version < 3.0 2020-11-09 16:20:08 +01:00
Moritz Raabe
dfc805b89b improvements for PR #355 2020-11-09 13:39:19 +01:00
Moritz Raabe
75defc13a0 disable fail-fast for tests job 2020-11-09 13:22:23 +01:00
Daniel Plohmann (jupiter)
7d4888bb77 addressing the comments in the PR discussion 2020-11-06 10:09:06 +01:00
Daniel Plohmann (jupiter)
1a34029171 Merge branch 'master' of github.com:fireeye/capa into backend-smda 2020-11-06 09:50:09 +01:00
Willi Ballenthin
f6ad4652e4 Merge pull request #358 from fireeye/doc/pyinstaller
document PyInstaller build process
2020-11-05 09:19:51 -07:00
pnx@pyrite
1e25604b0b replacement test for nested x64 thunks - still needs to be verified for vivisect 2020-11-05 16:31:47 +01:00
pnx@pyrite
3a43ffa641 adjusted identification of thunks via SMDA. 2020-11-05 12:58:07 +01:00
Capa Bot
8f6bcf3d98 Sync capa rules submodule 2020-11-03 14:23:36 +00:00
Moritz Raabe
0fd9753681 document PyInstaller build process
closes #357
2020-11-03 15:03:32 +01:00
Capa Bot
76a04dfe25 Sync capa rules submodule 2020-11-03 13:20:30 +00:00
Capa Bot
16317182e3 Sync capa-testfiles submodule 2020-11-03 13:14:45 +00:00
Daniel Plohmann (jupiter)
6bcdf64f67 formatting 2020-10-30 15:34:02 +01:00
Daniel Plohmann (jupiter)
d276a07a71 comments on a test where disassembly differs among backends 2020-10-30 15:29:38 +01:00
Daniel Plohmann (jupiter)
f3b59b342a Merge branch 'backend-smda' of github.com:danielplohmann/capa into backend-smda 2020-10-30 15:25:45 +01:00
Daniel Plohmann (jupiter)
4a0f1f22ba test fixes 2020-10-30 15:25:42 +01:00
Jon Crussell
0c85e7604c use magical derefs
Found derefs in viv/insn.py, does exactly what we need!
2020-10-30 07:23:24 -07:00
Jon Crussell
8f6a46e2d8 add check for pointer to string
Check if memory referenced is a pointer to a string. Fixes mimikatz
string test.
2020-10-30 07:01:07 -07:00
Daniel Plohmann (jupiter)
74b2c18296 down to 14 failed 2020-10-29 20:05:50 +01:00
Jon Crussell
b12d0b6424 tests: add smda backend test
40 failed, 73 passed.
2020-10-29 09:56:28 -07:00
Daniel Plohmann (jupiter)
60ddf0400e addressing review 2020-10-29 17:47:10 +01:00
Daniel Plohmann (jupiter)
669d3484c0 Merge remote-tracking branch 'origin/master' into backend-smda 2020-10-29 17:38:21 +01:00
William Ballenthin
5420ad97a3 sync submodules 2020-10-29 09:42:56 -06:00
Daniel Plohmann (jupiter)
36822926af initial commit for backend-smda 2020-10-29 11:28:22 +01:00
Capa Bot
eef8f2e781 Sync capa rules submodule 2020-10-29 03:50:40 +00:00
Capa Bot
31ac667623 Sync capa rules submodule 2020-10-27 15:16:07 +00:00
Capa Bot
868ceb25bf Sync capa rules submodule 2020-10-27 15:15:30 +00:00
Capa Bot
ee3ab94774 Sync capa rules submodule 2020-10-27 15:15:04 +00:00
Capa Bot
1c47877a8c Sync capa rules submodule 2020-10-27 15:14:22 +00:00
Capa Bot
84698462f3 Sync capa rules submodule 2020-10-27 15:13:25 +00:00
Capa Bot
da7dc793e7 Sync capa rules submodule 2020-10-27 15:12:51 +00:00
Capa Bot
044ee83fbc Sync capa-testfiles submodule 2020-10-26 16:48:15 +00:00
Capa Bot
aea324c4a8 Sync capa rules submodule 2020-10-26 16:47:44 +00:00
Capa Bot
4d05b20830 Sync capa rules submodule 2020-10-26 16:46:53 +00:00
Willi Ballenthin
276928951c build: event published/edited, not created 2020-10-23 15:17:32 -06:00
Willi Ballenthin
9486654e77 changelog: v1.4.1 2020-10-23 15:13:22 -06:00
Willi Ballenthin
2a2b4cbb06 Merge pull request #351 from fireeye/ci-build-windows-vcpython27
fix build on windows-latest
2020-10-23 15:10:56 -06:00
Willi Ballenthin
3ba4a8cdd8 Update build.yml 2020-10-23 15:07:13 -06:00
Willi Ballenthin
8820dabab9 Update build.yml 2020-10-23 14:59:34 -06:00
Willi Ballenthin
f9d89301df Update build.yml 2020-10-23 14:58:44 -06:00
Willi Ballenthin
7edb93d3ad Update build.yml 2020-10-23 14:57:14 -06:00
Moritz
5c5d9974e1 Merge pull request #350 from fireeye/release-1.4.0
release v1.4.0
2020-10-23 22:31:00 +02:00
Moritz Raabe
b0bf4f8f8e prepare new release 2020-10-23 22:24:50 +02:00
Capa Bot
04ea03caf6 Sync capa rules submodule 2020-10-23 18:50:52 +00:00
Capa Bot
cf0841bdcc Sync capa-testfiles submodule 2020-10-23 18:49:05 +00:00
Capa Bot
cc4f5f66d8 Sync capa-testfiles submodule 2020-10-23 18:42:54 +00:00
Capa Bot
e6d75ee7c4 Sync capa rules submodule 2020-10-23 16:46:53 +00:00
Moritz
61986fc98c Merge pull request #333 from fireeye/improve-packaging-setup
add long description and other improvements
2020-10-23 13:16:13 +02:00
Moritz
0e009c7c12 Merge pull request #347 from fireeye/fix/non-ascii-char-filename
get decoded sample path
2020-10-23 13:15:36 +02:00
Moritz
425613ee42 Merge pull request #346 from fireeye/extract/api-jmps
Extract/api jmps
2020-10-23 13:15:10 +02:00
Moritz Raabe
679316946e addressing Willi's feedback 2020-10-22 20:10:47 +02:00
Moritz
8bb305038b Merge pull request #343 from fireeye/fix/file-imports-ordinal-name
extract ordinal and name imports
2020-10-22 20:07:42 +02:00
Moritz Raabe
fbe104d254 get decoded sample path
closes #328
2020-10-22 19:56:41 +02:00
Capa Bot
cb44cb0ee2 Sync capa-testfiles submodule 2020-10-22 17:49:54 +00:00
Capa Bot
2163f64877 Sync capa-testfiles submodule 2020-10-22 17:49:18 +00:00
Capa Bot
a14d958ef0 Sync capa-testfiles submodule 2020-10-22 13:17:55 +00:00
Capa Bot
c65ef12783 Sync capa rules submodule 2020-10-22 04:02:25 +00:00
Capa Bot
8eb1727c76 Sync capa rules submodule 2020-10-21 15:54:41 +00:00
William Ballenthin
fafe24295a Merge branch 'master' of github.com:fireeye/capa 2020-10-21 09:53:09 -06:00
William Ballenthin
d900a6c145 render: default: sanity check MBC 2020-10-21 09:52:40 -06:00
Capa Bot
03df2fa3e9 Sync capa rules submodule 2020-10-21 15:43:31 +00:00
Moritz Raabe
69a4b99d70 extract apis called via jmp
closes #337
2020-10-21 12:39:45 +02:00
Capa Bot
39d95b2fd2 Sync capa rules submodule 2020-10-21 10:21:54 +00:00
Moritz Raabe
1e3b29de2e add IDA specific test 2020-10-21 12:16:50 +02:00
Moritz
d5186f160d Merge pull request #342 from fireeye/viv/extractor/api-thunk-chains
extract api features for thunk chains
2020-10-21 11:37:58 +02:00
Capa Bot
5d7dbd15c7 Sync capa-testfiles submodule 2020-10-21 09:35:22 +00:00
Moritz Raabe
12d5fe0afe addressing feedback 2020-10-21 11:25:08 +02:00
Capa Bot
3df1cc9038 Sync capa rules submodule 2020-10-20 21:04:10 +00:00
Willi Ballenthin
d46152b73e Merge pull request #345 from fireeye/fix/build-workflow-set-env-var
set env var via environment file
2020-10-20 09:55:26 -06:00
Moritz Raabe
9fc6e0d6a2 Merge branch 'enhance/show-features' into viv/extractor/api-thunk-chains 2020-10-20 15:26:51 +02:00
Moritz Raabe
4994d0597f set env var via environment file 2020-10-20 15:14:36 +02:00
Moritz Raabe
76b46d7957 ensure function is defined in vivisect (or do so)
and show features in IDA
2020-10-20 15:09:07 +02:00
Moritz Raabe
0a369c548b extract ordinal and name imports 2020-10-20 14:56:38 +02:00
Moritz Raabe
9a738ba413 extract api features for thunk chains
closes #341
2020-10-20 14:49:09 +02:00
Moritz
a442536246 Merge pull request #340 from fireeye/ida/extractor/improve-api-thunk-detection
ida/extractor: improve detection of APIs called via two or more chained thunks
2020-10-19 20:51:16 +02:00
Capa Bot
f85b6fde7b Sync capa rules submodule 2020-10-16 16:05:56 +00:00
Capa Bot
8dc6a5109a Sync capa-testfiles submodule 2020-10-15 21:00:58 +00:00
Michael Hunhoff
235d9d4ab5 improve detection of APIs called via two or more chained thunks 2020-10-15 14:31:23 -06:00
Capa Bot
3572de058b Sync capa rules submodule 2020-10-08 18:16:59 +00:00
Capa Bot
93068aff1b Sync capa-testfiles submodule 2020-10-08 18:16:15 +00:00
Capa Bot
49e7d75ce5 Sync capa rules submodule 2020-10-08 15:53:20 +00:00
Capa Bot
6aa1ecd1a8 Sync capa-testfiles submodule 2020-10-08 15:52:23 +00:00
Capa Bot
b442fbb19c Sync capa rules submodule 2020-10-07 20:58:02 +00:00
Capa Bot
46fc4f0c25 Sync capa-testfiles submodule 2020-10-07 20:57:34 +00:00
Capa Bot
155de6f2b9 Sync capa rules submodule 2020-10-06 16:30:56 +00:00
Capa Bot
459af7ab1b Sync capa rules submodule 2020-10-06 02:36:03 +00:00
Willi Ballenthin
2bd408a274 Merge pull request #338 from fireeye/fix/feature-str
fix feature display
2020-10-05 14:19:54 -06:00
Moritz Raabe
bc1c5a59f8 display value including 0 2020-10-05 22:10:04 +02:00
Willi Ballenthin
49cecdc75d Merge pull request #336 from fireeye/fix-335
modify find_byte_sequence to yield all locations
2020-10-05 11:02:36 -06:00
Capa Bot
2a6aeae763 Sync capa rules submodule 2020-10-05 17:02:21 +00:00
Michael Hunhoff
f295e1da31 modify find_byte_sequence to yield all locations, instead of only first 2020-10-05 10:27:45 -06:00
Capa Bot
1981859343 Sync capa rules submodule 2020-10-05 16:11:30 +00:00
Capa Bot
9de237e1a3 Sync capa-testfiles submodule 2020-10-05 14:18:32 +00:00
Moritz Raabe
77b412c1e8 add long description and other improvements 2020-10-02 17:08:03 +02:00
Moritz
a31529bb79 Merge pull request #332 from fireeye/render-mbc
render mbc table
2020-10-02 11:09:39 +02:00
Moritz Raabe
00bc1a169e render mbc table 2020-10-01 11:10:03 +02:00
Capa Bot
3e98cac397 Sync capa rules submodule 2020-10-01 09:00:31 +00:00
Capa Bot
8cd0777683 Sync capa rules submodule 2020-10-01 08:32:39 +00:00
Capa Bot
8bac77c2ab Sync capa rules submodule 2020-10-01 07:57:13 +00:00
Capa Bot
3312e1b20b Sync capa rules submodule 2020-09-30 17:27:42 +00:00
Capa Bot
d55e2a2647 Sync capa rules submodule 2020-09-28 15:03:30 +00:00
Willi Ballenthin
e87d9cd1b5 Merge pull request #330 from fireeye/fix-329
fix 329
2020-09-28 09:01:34 -06:00
Michael Hunhoff
5dda95385d use rpartition in capa.features.insn.API to handle API name w/ multiple . 2020-09-28 08:33:08 -06:00
Willi Ballenthin
d60bdb561e Merge pull request #327 from fireeye/fix/312-statement-descriptions
parse descriptions for statements
2020-09-25 11:50:47 -06:00
Capa Bot
fab89beba0 Sync capa rules submodule 2020-09-25 17:49:24 +00:00
Moritz Raabe
1cb9ed9c01 addressing final comments 2020-09-25 18:38:46 +02:00
Moritz Raabe
00b7f2e02f addressing Willi's feedback 2020-09-24 20:23:15 +02:00
Moritz Raabe
4691302a78 parse descriptions for statements 2020-09-24 15:35:30 +02:00
Willi Ballenthin
d8a32630fb Merge pull request #326 from fireeye/fix-325
main: fix reported total rule count
2020-09-23 16:07:22 -06:00
Willi Ballenthin
29b6bd8aad Merge pull request #324 from fireeye/fix-307
scripts: add script demonstrating bulk processing
2020-09-23 14:45:56 -06:00
William Ballenthin
c2516e7453 main: fix reported total rule count
closes #325
2020-09-23 11:19:01 -06:00
Willi Ballenthin
1fd8c3c068 Merge pull request #323 from fireeye/fix-306
use PyYAML CLoader to parse rules when available
2020-09-23 10:01:15 -06:00
William Ballenthin
314757a235 scripts: add script demonstrating bulk processing
closes #307
2020-09-23 09:13:49 -06:00
William Ballenthin
5b613903e5 rules: fix ordering of meta under py2 2020-09-23 06:32:22 -06:00
Capa Bot
b2caad9b4b Sync capa rules submodule 2020-09-22 18:49:29 +00:00
William Ballenthin
4b066e908c ci: use sudo to apt 2020-09-22 11:20:15 -06:00
William Ballenthin
041e443619 ci: install libyaml when appropriate 2020-09-22 11:18:15 -06:00
William Ballenthin
999bd84a86 rules: fall back to python pyyaml when libyaml not present 2020-09-22 11:06:48 -06:00
William Ballenthin
2a894fb5f6 rules: fall back to python based yaml parser when libyaml not present 2020-09-22 10:54:53 -06:00
William Ballenthin
79bf5c2d6b rules: use yaml.CLoader for better performance 2020-09-22 10:46:05 -06:00
Capa Bot
98298a3b2d Sync capa rules submodule 2020-09-21 18:03:51 +00:00
Capa Bot
71454c6400 Sync capa-testfiles submodule 2020-09-21 09:33:08 +00:00
Capa Bot
5e2e316474 Sync capa rules submodule 2020-09-18 20:47:00 +00:00
Capa Bot
6bca211267 Sync capa rules submodule 2020-09-18 18:37:14 +00:00
Moritz
f8cbc0a12d Merge pull request #321 from fireeye/ida/explorer-update-documentation
explorer: documentation updates, logo
2020-09-18 17:03:19 +02:00
Capa Bot
9708c89772 Sync capa rules submodule 2020-09-18 14:26:29 +00:00
Michael Hunhoff
29492bfdc8 fixing feature count for explorer progress indicator 2020-09-17 14:50:14 -06:00
Capa Bot
d2e05f03cc Sync capa rules submodule 2020-09-17 18:34:36 +00:00
Capa Bot
01bf7b3bd3 Sync capa rules submodule 2020-09-17 18:07:50 +00:00
Capa Bot
db790ab20c Sync capa-testfiles submodule 2020-09-17 18:01:18 +00:00
Capa Bot
71c19a1fbc Sync capa rules submodule 2020-09-17 15:02:03 +00:00
Capa Bot
73e9b6e804 Sync capa rules submodule 2020-09-17 15:01:25 +00:00
Michael Hunhoff
199e9fc81d Merge branch 'master' into ida/explorer-update-documentation 2020-09-16 13:55:24 -06:00
Michael Hunhoff
a9591aad1b updating explorer documentation link 2020-09-16 13:53:47 -06:00
Michael Hunhoff
0168f444d9 removing old .jpg, adding explorer logo, updating explorer readme 2020-09-16 13:33:11 -06:00
mike-hunhoff
4659ab0649 Merge pull request #316 from fireeye/fix-315
explorer: add additional check for invalid model index
2020-09-16 08:40:59 -06:00
Michael Hunhoff
49700ffb9f add check for invalid model index, fix 315 2020-09-16 08:27:38 -06:00
Moritz
6c6062d5a8 Update usage.md 2020-09-15 10:31:08 +02:00
Moritz
01e8b198c0 Update installation.md 2020-09-15 10:13:41 +02:00
Willi Ballenthin
90b070296b pyinstaller: fix viv pe parser 2020-09-14 15:54:23 -06:00
Willi Ballenthin
9302c0a98e Merge pull request #295 from fireeye/release-1.3.0
release v1.3.0
2020-09-14 15:45:46 -06:00
Michael Hunhoff
6d98efb1e4 updating plugin documentation 2020-09-14 15:30:41 -06:00
mike-hunhoff
04e6e1964d Merge pull request #314 from fireeye/ida/explorer_progress_indicator
explorer: progress indicator
2020-09-14 15:19:37 -06:00
Michael Hunhoff
a02235e894 PR change requests 2020-09-14 15:12:35 -06:00
Capa Bot
69751ab8c5 Sync capa rules submodule 2020-09-14 21:00:09 +00:00
mike-hunhoff
c4fdd0db8a Update CHANGELOG.md 2020-09-14 14:43:08 -06:00
Michael Hunhoff
a45dbba4b1 bug fixes for program rebase hook 2020-09-14 14:30:27 -06:00
Michael Hunhoff
89e409157f updating progress message 2020-09-14 13:58:30 -06:00
mike-hunhoff
b64ad56caa Merge pull request #310 from fireeye/ida_plugin_documentation
ida plugin: update documentation
2020-09-14 12:48:47 -06:00
Michael Hunhoff
498fd3fe62 PR change requests 2020-09-14 12:39:41 -06:00
Michael Hunhoff
0d93df7d59 updating documentation 2020-09-14 11:29:17 -06:00
Michael Hunhoff
725361c949 add progress indicator wait box 2020-09-14 11:11:40 -06:00
Willi Ballenthin
8510f04651 Merge pull request #294 from fireeye/fix-293
docs: installation: clarify when to use method 2
2020-09-11 20:43:41 -06:00
Willi Ballenthin
ddf7f0d0e6 changelog: recognize @stevemk14ebr 2020-09-11 20:20:53 -06:00
mike-hunhoff
cfbc906cb3 Update CHANGELOG.md 2020-09-11 17:39:35 -06:00
mike-hunhoff
5915ec68bc Merge pull request #311 from fireeye/fix-309
fix: 309
2020-09-11 17:14:39 -06:00
Michael Hunhoff
ffae162955 updating plugin documentation 2020-09-11 17:05:24 -06:00
Michael Hunhoff
4aaeed8c88 fix #309 2020-09-11 17:03:00 -06:00
Michael Hunhoff
33ac728af8 merging upstream 2020-09-11 13:18:45 -06:00
Michael Hunhoff
7846ffa818 updating ida plugin documentation 2020-09-11 13:15:32 -06:00
mike-hunhoff
2e8d02c0ab Merge pull request #308 from fireeye/ida_plugin_rename
ida plugin: new name
2020-09-11 13:14:08 -06:00
Michael Hunhoff
1cb45f35be rename ida plugin 2020-09-11 13:12:28 -06:00
mike-hunhoff
ca47a6ca51 Merge pull request #305 from fireeye/ida_plugin_highlight_regex
ida plugin: highlight regex matches in IDA ui
2020-09-10 17:31:55 -06:00
Michael Hunhoff
1cee930055 highlight regex in IDA ui 2020-09-10 17:19:52 -06:00
mike-hunhoff
196d394ebd Merge pull request #304 from fireeye/plugin_ui_updates
ida plugin: ui improvements
2020-09-10 15:07:51 -06:00
Michael Hunhoff
883af122f1 plugin ui improvements 2020-09-10 14:42:54 -06:00
mike-hunhoff
0cb1b6a74f Merge pull request #303 from fireeye/explorer_performance_enhancements
ida plugin: performance enchancements
2020-09-09 16:29:11 -06:00
Michael Hunhoff
59f3a1894a changes for isort 2020-09-09 13:11:37 -06:00
Michael Hunhoff
f076d0e00e minor formatting changes 2020-09-09 13:10:12 -06:00
Michael Hunhoff
697ec9736e merge conflicts 2020-09-09 12:45:35 -06:00
Michael Hunhoff
793c9a276b merging upstream 2020-09-09 12:41:54 -06:00
Michael Hunhoff
ae48671168 explorer performance enhancements 2020-09-09 12:40:03 -06:00
mike-hunhoff
e48e966794 Merge pull request #302 from fireeye/fix-299
fix 299 and add make search case insensitive
2020-09-09 11:34:46 -06:00
Michael Hunhoff
6f3560c680 fix 299 and add make search case insensitive 2020-09-09 11:26:24 -06:00
mike-hunhoff
146caed7aa Merge pull request #301 from fireeye/fix-298
ida plugin: don't use rule path settings if the path doesn't exist
2020-09-09 10:58:30 -06:00
Willi Ballenthin
95b4c55ea2 ida plugin: don't use rule path settings if the path doesn't exist
closes #298
2020-09-09 10:36:48 -06:00
Willi Ballenthin
8cd90e5c2d setup: bump ida-settings to 2.1.0 2020-09-09 10:33:36 -06:00
Willi Ballenthin
5d02410e1e changelog: recognize weslambert 2020-09-08 15:27:32 -06:00
Willi Ballenthin
09da1d1af0 setup: bump viv dep to v0.1.0 2020-09-08 15:22:40 -06:00
mike-hunhoff
e1c7993731 Merge pull request #296 from fireeye/explorer-documentation-updates 2020-09-08 12:42:12 -06:00
Michael Hunhoff
84aea98448 merging upstream 2020-09-08 12:29:13 -06:00
mike-hunhoff
93039df3ef Merge pull request #290 from edeca/master 2020-09-08 12:28:06 -06:00
Michael Hunhoff
f9451feb18 changes to plugin function-level documentation 2020-09-08 12:26:20 -06:00
Capa Bot
35e46654df Sync capa rules submodule 2020-09-07 18:24:05 +00:00
Willi Ballenthin
df32d3f195 changelog: recognize @adamprescott91 2020-09-07 12:20:22 -06:00
Willi Ballenthin
4457207a87 changelog: document v1.3.0 2020-09-07 12:11:02 -06:00
Willi Ballenthin
fa5f4d209a version: bump to v1.3.0 2020-09-07 11:36:30 -06:00
Willi Ballenthin
aecf939366 setup: bump ida-settings dependency
closes #288 
closes #289
2020-09-07 11:31:28 -06:00
Willi Ballenthin
2c6e244b3c docs: installation: clarify when to use method 2 2020-09-07 10:55:55 -06:00
Willi Ballenthin
6243e85b6f Merge pull request #292 from cclauss/patch-2
GitHub Action: Test Python 3.9 release candidate 1
2020-09-07 10:44:09 -06:00
Willi Ballenthin
3f194f6584 Merge pull request #291 from cclauss/patch-1
Undefined name: import ida_funcs for lines 48, 52, 57
2020-09-07 10:43:43 -06:00
Christian Clauss
47dc4d39eb GitHub Action: Test Python 3.9 release candidate 1 2020-09-07 09:52:15 +02:00
Christian Clauss
5f184b278f Undefined name: import ida_funcs for lines 48, 52, 57 2020-09-07 09:48:42 +02:00
David Cannings
854e586f40 Fix #280: Test if op is an offset
Check whether the auto-analyser (or user) has marked an operand as an offset, instead of checking whether the value is mapped.
2020-09-05 16:00:36 +01:00
Capa Bot
6044275346 Sync capa rules submodule 2020-09-03 18:51:13 +00:00
Capa Bot
e10f6a2d58 Sync capa-testfiles submodule 2020-09-03 18:22:59 +00:00
Willi Ballenthin
c4eab0de2b Merge pull request #287 from fireeye/fix-286
fix 286
2020-09-02 14:50:24 -06:00
Willi Ballenthin
cf961a7c92 Merge branch 'master' into fix-286 2020-09-02 14:46:30 -06:00
Willi Ballenthin
8f820e4bb8 Merge pull request #285 from fireeye/fix-212-2
ida plugin: add search bar
2020-09-02 14:45:12 -06:00
Willi Ballenthin
e23e552084 ida plugin: fix typo 2020-09-02 14:38:13 -06:00
Willi Ballenthin
d964e82fdc Merge pull request #284 from fireeye/fix-224
render: dont display rules that are also matched as subrule matches
2020-09-02 14:36:47 -06:00
Willi Ballenthin
f6f7b46fa0 Merge branch 'fix-212-2' into fix-286 2020-09-02 13:57:43 -06:00
Willi Ballenthin
e45151cdb8 Merge branch 'fix-212-2' of github.com:fireeye/capa into fix-212-2 2020-09-02 13:56:26 -06:00
Willi Ballenthin
e8cf19caf4 ida plugin: fix context menu 2020-09-02 13:55:46 -06:00
Willi Ballenthin
aebdc60c7e ida plugin: filter on all columns 2020-09-02 13:55:16 -06:00
William Ballenthin
e5f2ed4920 pep8 2020-09-02 13:16:43 -06:00
William Ballenthin
5506175bff Merge branch 'fix-212-2' into fix-286 2020-09-02 13:15:11 -06:00
William Ballenthin
e2c0a702b1 pep8 2020-09-02 13:14:45 -06:00
Willi Ballenthin
398f685b08 ida plugin: remove summary tab 2020-09-02 13:10:46 -06:00
Willi Ballenthin
2e0ab52a77 ida plugin: show tree view by default 2020-09-02 13:07:23 -06:00
Willi Ballenthin
a2a65b7553 ida plugin: show rule namespace in details column 2020-09-02 13:05:38 -06:00
Willi Ballenthin
881c7984aa ida plugin: search for matches across all columns 2020-09-02 13:05:18 -06:00
Capa Bot
7de0a5414a Sync capa rules submodule 2020-09-02 18:26:38 +00:00
Willi Ballenthin
98143d13f8 ida plugin: add search bar
closes #212
2020-09-02 12:01:09 -06:00
William Ballenthin
a25a86e2d6 render: dont display rules that are also matched as subrule matches
closes #224
2020-09-02 10:20:54 -06:00
Willi Ballenthin
0833f06439 Merge pull request #283 from fireeye/enhancements/ida-plugin-2
Various enhancements IDA plugin
2020-09-02 10:19:53 -06:00
Moritz Raabe
7e9a3d649a use embedded icon
(cherry picked from commit bbc41dff09)
2020-09-02 17:50:25 +02:00
Moritz Raabe
d6aa10164a menu changes and rebase hook
(cherry picked from commit 2924c973eb)
2020-09-02 17:16:11 +02:00
Moritz Raabe
198fabdd2d add form icon and other cosmetic changes
(cherry picked from commit 98ed862d3c)
2020-09-02 17:15:16 +02:00
Moritz
ba47455a0c Merge pull request #281 from fireeye/fix-275-3
provide an icon for the ida plugin
2020-09-02 16:32:36 +02:00
Willi Ballenthin
e65e2b8706 ida: document the embedded icon
(cherry picked from commit 84757ed97d)
2020-09-02 14:03:01 +02:00
Willi Ballenthin
e28c8a16eb ida: plugin: use icon
closes #275

(cherry picked from commit f0f958b28e)
2020-09-02 14:02:35 +02:00
Moritz
76ab5da49b Merge pull request #278 from fireeye/fix-268
ida: use ida-settings to persist rules directory
2020-09-02 09:27:57 +02:00
William Ballenthin
3d6d38c4fb setup: fix ida-settings spec 2020-09-01 17:53:10 -06:00
William Ballenthin
ea6698e27a pep8 2020-09-01 17:52:29 -06:00
Willi Ballenthin
b611ddeb6e ida: use ida-settings to persist rules directory
closes #268
2020-09-01 16:12:50 -06:00
Willi Ballenthin
bf90dc075e Merge pull request #274 from fireeye/fix-246
fix 246
2020-09-01 15:51:58 -06:00
William Ballenthin
99d5f06383 pep8 2020-09-01 15:50:24 -06:00
Capa Bot
b386933a04 Sync capa rules submodule 2020-09-01 18:13:40 +00:00
Willi Ballenthin
76447d65a0 Merge pull request #277 from fireeye/fix-276
fix 276
2020-09-01 11:36:23 -06:00
Capa Bot
08099f93a1 Sync capa-testfiles submodule 2020-09-01 16:56:04 +00:00
Willi Ballenthin
cbabf5650d Merge pull request #273 from fireeye/fix-263
fix 263
2020-09-01 10:50:41 -06:00
Willi Ballenthin
82f20f102e Merge pull request #272 from fireeye/fix-262
fix 262
2020-09-01 10:50:17 -06:00
William Ballenthin
2b2656c2a3 features: extractors: merge import and API variant generators 2020-09-01 01:04:51 -06:00
William Ballenthin
330c0f055e Merge branch 'master' into fix-246 2020-08-31 22:30:39 -06:00
William Ballenthin
d272006873 features: insn: viv: extract offset from SibOper operands
closes #276
2020-08-31 20:41:45 -06:00
William Ballenthin
5f7f718fe4 tests: add test for #276 2020-08-31 20:31:36 -06:00
William Ballenthin
13abd175aa pep8 2020-08-31 17:15:30 -06:00
William Ballenthin
090ec46ca4 features: extract import A/W variants and their base names
closes #246
2020-08-31 17:13:10 -06:00
William Ballenthin
5b349c1df8 tests: add feature tests for #246 2020-08-31 16:59:55 -06:00
William Ballenthin
7310b0feda rules: documentation formatting 2020-08-31 16:55:54 -06:00
William Ballenthin
7e0ebb8c5b rules: fmt: fix formatting of description block
closes #263
2020-08-31 16:49:54 -06:00
William Ballenthin
0734edf6f0 tests: fmt: add test for #263 2020-08-31 16:34:10 -06:00
William Ballenthin
4656275ee0 features: documentation wording 2020-08-31 16:20:30 -06:00
William Ballenthin
076a47de1c features: fix matching of a regex multiple times 2020-08-31 16:15:33 -06:00
Willi Ballenthin
2bd0c03f70 Merge pull request #270 from fireeye/explorer_run_as_ida_plugin
explorer: run as IDA plugin
2020-08-31 15:54:53 -06:00
William Ballenthin
322d2ad549 tests: main: add tests for #262 2020-08-31 15:51:49 -06:00
Michael Hunhoff
e18eb5f463 addressing PR comments 2020-08-31 15:42:44 -06:00
William Ballenthin
fb4ef6b993 tests: add tests for #262 2020-08-31 15:38:07 -06:00
Michael Hunhoff
863b7b58c5 fixing merge conflicts 2020-08-31 15:09:46 -06:00
Capa Bot
3bac5e7e43 Sync capa rules submodule 2020-08-31 21:01:16 +00:00
Capa Bot
846b40de9f Sync capa-testfiles submodule 2020-08-31 20:59:52 +00:00
Willi Ballenthin
d48bfe81ac Merge pull request #269 from fireeye/fix-254
use vivisect from pypi and other packaging
2020-08-31 14:58:57 -06:00
William Ballenthin
4d03856c26 ci: publish: formatting 2020-08-31 14:35:14 -06:00
Capa Bot
ed0f4f994c Sync capa rules submodule 2020-08-31 20:19:29 +00:00
Capa Bot
f9eed2d5b2 Sync capa rules submodule 2020-08-31 19:19:49 +00:00
Michael Hunhoff
6b5d3978cf Merge branch 'master' into explorer_run_as_ida_plugin 2020-08-31 09:23:48 -06:00
William Ballenthin
381e4abd17 ci: publish: tweak event to on published 2020-08-30 02:46:50 -06:00
William Ballenthin
7ab42d9889 ci: publish: trigger on pre-release 2020-08-30 02:32:09 -06:00
William Ballenthin
b3c3c5579b pyinstaller: update spec to account for viv changes 2020-08-30 02:29:56 -06:00
William Ballenthin
2d20fe20c4 ci: publish to pypi upon tag 2020-08-30 02:13:27 -06:00
William Ballenthin
c4e4eb27fb setup: use vivisect from pypi
closes #254
2020-08-30 02:03:15 -06:00
Michael Hunhoff
96eaf311d0 adding support to run explorer as IDA plugin 2020-08-28 17:38:13 -06:00
232 changed files with 40201 additions and 8364 deletions

21
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.233.0/containers/python-3/.devcontainer/base.Dockerfile
# [Choice] Python version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.10, 3.9, 3.8, 3.7, 3.6, 3-bullseye, 3.10-bullseye, 3.9-bullseye, 3.8-bullseye, 3.7-bullseye, 3.6-bullseye, 3-buster, 3.10-buster, 3.9-buster, 3.8-buster, 3.7-buster, 3.6-buster
ARG VARIANT="3.10-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
ARG NODE_VERSION="none"
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
# [Optional] If your pip requirements rarely change, uncomment this section to add them to the image.
# COPY requirements.txt /tmp/pip-tmp/
# RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
# && rm -rf /tmp/pip-tmp
# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1

View File

@@ -0,0 +1,51 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.233.0/containers/python-3
{
"name": "Python 3",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
// Update 'VARIANT' to pick a Python version: 3, 3.10, 3.9, 3.8, 3.7, 3.6
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local on arm64/Apple Silicon.
"VARIANT": "3.10",
// Options
"NODE_VERSION": "none"
}
},
// Set *default* container specific settings.json values on container create.
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "git submodule update --init && pip3 install --user -e .[dev] && pre-commit install",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
"features": {
"git": "latest"
}
}

9
.gitattributes vendored Normal file
View File

@@ -0,0 +1,9 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.py text
*.yml text
*.md text
*.txt text

View File

@@ -1,46 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/

View File

@@ -1,197 +1,210 @@
# Contributing to Capa
First off, thanks for taking the time to contribute!
The following is a set of guidelines for contributing to capa and its packages, which are hosted in the [FireEye Organization](https://github.com/fireeye) on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
#### Table Of Contents
[Code of Conduct](#code-of-conduct)
[What should I know before I get started?](#what-should-i-know-before-i-get-started)
* [Capa and its Repositories](#capa-and-its-repositories)
* [Capa Design Decisions](#design-decisions)
[How Can I Contribute?](#how-can-i-contribute)
* [Reporting Bugs](#reporting-bugs)
* [Suggesting Enhancements](#suggesting-enhancements)
* [Your First Code Contribution](#your-first-code-contribution)
* [Pull Requests](#pull-requests)
[Styleguides](#styleguides)
* [Git Commit Messages](#git-commit-messages)
* [Python Styleguide](#python-styleguide)
* [Rules Styleguide](#rules-styleguide)
## Code of Conduct
This project and everyone participating in it is governed by the [Capa Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to the maintainers.
## What should I know before I get started?
### Capa and its repositories
We host the capa project as three Github repositories:
- [capa](https://github.com/fireeye/capa)
- [capa-rules](https://github.com/fireeye/capa-rules)
- [capa-testfiles](https://github.com/fireeye/capa-testfiles)
The command line tools, logic engine, and other Python source code are found in the `capa` repository.
This is the repository to fork when you want to enhance the features, performance, or user interface of capa.
Do *not* push rules directly to this repository, instead...
The standard rules contributed by the community are found in the `capa-rules` repository.
When you have an idea for a new rule, you should open a PR against `capa-rules`.
We keep `capa` and `capa-rules` separate to distinguish where ideas, bugs, and discussions should happen.
If you're writing yaml it probably goes in `capa-rules` and if you're writing Python it probably goes in `capa`.
Also, we encourage users to develop their own rule repositories, so we treat our default set of rules in the same way.
Test fixtures, such as malware samples and analysis workspaces, are found in the `capa-testfiles` repository.
These are files you'll need in order to run the linter (in `--thorough` mode) and full test suites;
however, they take up a lot of space (1GB+), so by keeping `capa-testfiles` separate,
a shallow checkout of `capa` and `capa-rules` doesn't take much bandwidth.
### Design Decisions
When we make a significant decision in how we maintain the project and what we can or cannot support,
we will document it in the [capa issues tracker](https://github.com/fireeye/capa/issues).
This is the best place review our discussions about what/how/why we do things in the project.
If you have a question, check to see if it is documented there.
If it is *not* documented there, or you can't find an answer, please open a issue.
We'll link to existing issues when appropriate to keep discussions in one place.
## How Can I Contribute?
### Reporting Bugs
This section guides you through submitting a bug report for capa.
Following these guidelines helps maintainers and the community understand your report, reproduce the behavior, and find related reports.
Before creating bug reports, please check [this list](#before-submitting-a-bug-report)
as you might find out that you don't need to create one.
When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report).
Fill out [the required template](./ISSUE_TEMPLATE/bug_report.md),
the information it asks for helps us resolve issues faster.
> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
#### Before Submitting A Bug Report
* **Determine [which repository the problem should be reported in](#capa-and-its-repositories)**.
* **Perform a [cursory search](https://github.com/fireeye/capa/issues?q=is%3Aissue)** to see if the problem has already been reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Bug Report?
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/).
After you've determined [which repository](#capa-and-its-repositories) your bug is related to,
create an issue on that repository and provide the following information by filling in
[the template](./ISSUE_TEMPLATE/bug_report.md).
Explain the problem and include additional details to help maintainers reproduce the problem:
* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started capa, e.g. which command exactly you used in the terminal, or how you started capa otherwise.
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.**
* **Include screenshots and animated GIFs** which show you following the described steps and clearly demonstrate the problem. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
* **If you're reporting that capa crashed**, include the stack trace from the terminal. Include the stack trace in the issue in a [code block](https://help.github.com/articles/markdown-basics/#multiple-lines), a [file attachment](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests/), or put it in a [gist](https://gist.github.com/) and provide link to that gist.
* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below.
Provide more context by answering these questions:
* **Did the problem start happening recently** (e.g. after updating to a new version of capa) or was this always a problem?
* If the problem started happening recently, **can you reproduce the problem in an older version of capa?** What's the most recent version in which the problem doesn't happen? You can download older versions of capa from [the releases page](https://github.com/fireeye/capa/releases).
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
* If the problem is related to working with files (e.g. opening and editing files), **does the problem happen for all files and projects or only some?** Does the problem happen only when working with local or remote files (e.g. on network drives), with files of a specific type (e.g. only JavaScript or Python files), with large files or files with very long lines, or with files in a specific encoding? Is there anything else special about the files you are using?
Include details about your configuration and environment:
* **Which version of capa are you using?** You can get the exact version by running `capa --version` in your terminal.
* **What's the name and version of the OS you're using**?
### Suggesting Enhancements
This section guides you through submitting an enhancement suggestion for capa, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion and find related suggestions.
Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](./ISSUE_TEMPLATE/feature_request.md), including the steps that you imagine you would take if the feature you're requesting existed.
#### Before Submitting An Enhancement Suggestion
* **Determine [which repository the enhancement should be suggested in](#capa-and-its-repositories).**
* **Perform a [cursory search](https://github.com/fireeye/capa/issues?q=is%3Aissue)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Enhancement Suggestion?
Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](#capa-and-its-repositories) your enhancement suggestion is related to, create an issue on that repository and provide the following information:
* **Use a clear and descriptive title** for the issue to identify the suggestion.
* **Provide a step-by-step description of the suggested enhancement** in as many details as possible.
* **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
* **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of capa which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
* **Explain why this enhancement would be useful** to most capa users and isn't something that can or should be implemented as an external tool that uses capa as a library.
* **Specify which version of capa you're using.** You can get the exact version by running `capa --version` in your terminal.
* **Specify the name and version of the OS you're using.**
### Your First Code Contribution
Unsure where to begin contributing to capa? You can start by looking through these `good-first-issue` and `rule-idea` issues:
* [good-first-issue](https://github.com/fireeye/capa/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) - issues which should only require a few lines of code, and a test or two.
* [rule-idea](https://github.com/fireeye/capa-rules/issues?q=is%3Aissue+is%3Aopen+label%3A%22rule+idea%22) - issues that describe potential new rule ideas.
Both issue lists are sorted by total number of comments. While not perfect, number of comments is a reasonable proxy for impact a given change will have.
#### Local development
capa and all its resources can be developed locally.
For instructions on how to do this, see the "Method 3" section of the [installation guide](https://github.com/fireeye/capa/blob/master/doc/installation.md).
### Pull Requests
The process described here has several goals:
- Maintain capa's quality
- Fix problems that are important to users
- Engage the community in working toward the best possible capa
- Enable a sustainable system for capa's maintainers to review contributions
Please follow these steps to have your contribution considered by the maintainers:
1. Follow all instructions in [the template](PULL_REQUEST_TEMPLATE.md)
2. Follow the [styleguides](#styleguides)
3. After you submit your pull request, verify that all [status checks](https://help.github.com/articles/about-status-checks/) are passing <details><summary>What if the status checks are failing? </summary>If a status check is failing, and you believe that the failure is unrelated to your change, please leave a comment on the pull request explaining why you believe the failure is unrelated. A maintainer will re-run the status check for you. If we conclude that the failure was a false positive, then we will open an issue to track that problem with our status check suite.</details>
While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted.
## Styleguides
### Git Commit Messages
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Prefix the first line with the component in question ("rules: ..." or "render: ...")
* Reference issues and pull requests liberally after the first line
### Python Styleguide
All Python code must adhere to the style guide used by capa:
1. [PEP8](https://www.python.org/dev/peps/pep-0008/), with clarifications from
2. [Willi's style guide](https://docs.google.com/document/d/1iRpeg-w4DtibwytUyC_dDT7IGhNGBP25-nQfuBa-Fyk/edit?usp=sharing), formatted with
3. [isort](https://pypi.org/project/isort/) (with line width 120 and ordered by line length), and formatted with
4. [black](https://github.com/psf/black) (with line width 120), and formatted with
5. [dos2unix](https://linux.die.net/man/1/dos2unix)
Our CI pipeline will reformat and enforce the Python styleguide.
### Rules Styleguide
All (non-nursery) capa rules must:
1. pass the [linter](https://github.com/fireeye/capa/blob/master/scripts/lint.py), and
2. be formatted with [capafmt](https://github.com/fireeye/capa/blob/master/scripts/capafmt.py)
This ensures that all rules meet the same minimum level of quality and are structured in a consistent way.
Our CI pipeline will reformat and enforce the capa rules styleguide.
# Contributing to Capa
First off, thanks for taking the time to contribute!
The following is a set of guidelines for contributing to capa and its packages, which are hosted in the [Mandiant Organization](https://github.com/mandiant) on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
#### Table Of Contents
[Code of Conduct](#code-of-conduct)
[What should I know before I get started?](#what-should-i-know-before-i-get-started)
* [Capa and its Repositories](#capa-and-its-repositories)
* [Capa Design Decisions](#design-decisions)
[How Can I Contribute?](#how-can-i-contribute)
* [Reporting Bugs](#reporting-bugs)
* [Suggesting Enhancements](#suggesting-enhancements)
* [Your First Code Contribution](#your-first-code-contribution)
* [Pull Requests](#pull-requests)
[Styleguides](#styleguides)
* [Git Commit Messages](#git-commit-messages)
* [Python Styleguide](#python-styleguide)
* [Rules Styleguide](#rules-styleguide)
## Code of Conduct
This project and everyone participating in it is governed by the [Capa Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to the maintainers.
## What should I know before I get started?
### Capa and its repositories
We host the capa project as three GitHub repositories:
- [capa](https://github.com/mandiant/capa)
- [capa-rules](https://github.com/mandiant/capa-rules)
- [capa-testfiles](https://github.com/mandiant/capa-testfiles)
The command line tools, logic engine, and other Python source code are found in the `capa` repository.
This is the repository to fork when you want to enhance the features, performance, or user interface of capa.
Do *not* push rules directly to this repository, instead...
The standard rules contributed by the community are found in the `capa-rules` repository.
When you have an idea for a new rule, you should open a PR against `capa-rules`.
We keep `capa` and `capa-rules` separate to distinguish where ideas, bugs, and discussions should happen.
If you're writing yaml it probably goes in `capa-rules` and if you're writing Python it probably goes in `capa`.
Also, we encourage users to develop their own rule repositories, so we treat our default set of rules in the same way.
Test fixtures, such as malware samples and analysis workspaces, are found in the `capa-testfiles` repository.
These are files you'll need in order to run the linter (in `--thorough` mode) and full test suites;
however, they take up a lot of space (1GB+), so by keeping `capa-testfiles` separate,
a shallow checkout of `capa` and `capa-rules` doesn't take much bandwidth.
### Design Decisions
When we make a significant decision in how we maintain the project and what we can or cannot support,
we will document it in the [capa issues tracker](https://github.com/mandiant/capa/issues).
This is the best place review our discussions about what/how/why we do things in the project.
If you have a question, check to see if it is documented there.
If it is *not* documented there, or you can't find an answer, please open a issue.
We'll link to existing issues when appropriate to keep discussions in one place.
## How Can I Contribute?
### Reporting Bugs
This section guides you through submitting a bug report for capa.
Following these guidelines helps maintainers and the community understand your report, reproduce the behavior, and find related reports.
Before creating bug reports, please check [this list](#before-submitting-a-bug-report)
as you might find out that you don't need to create one.
When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report).
Fill out [the required template](./ISSUE_TEMPLATE/bug_report.md),
the information it asks for helps us resolve issues faster.
> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
#### Before Submitting A Bug Report
* **Determine [which repository the problem should be reported in](#capa-and-its-repositories)**.
* **Perform a [cursory search](https://github.com/mandiant/capa/issues?q=is%3Aissue)** to see if the problem has already been reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Bug Report?
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/).
After you've determined [which repository](#capa-and-its-repositories) your bug is related to,
create an issue on that repository and provide the following information by filling in
[the template](./ISSUE_TEMPLATE/bug_report.md).
Explain the problem and include additional details to help maintainers reproduce the problem:
* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started capa, e.g. which command exactly you used in the terminal, or how you started capa otherwise.
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.**
* **Include screenshots and animated GIFs** which show you following the described steps and clearly demonstrate the problem. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
* **If you're reporting that capa crashed**, include the stack trace from the terminal. Include the stack trace in the issue in a [code block](https://help.github.com/articles/markdown-basics/#multiple-lines), a [file attachment](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests/), or put it in a [gist](https://gist.github.com/) and provide link to that gist.
* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below.
Provide more context by answering these questions:
* **Did the problem start happening recently** (e.g. after updating to a new version of capa) or was this always a problem?
* If the problem started happening recently, **can you reproduce the problem in an older version of capa?** What's the most recent version in which the problem doesn't happen? You can download older versions of capa from [the releases page](https://github.com/mandiant/capa/releases).
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
* If the problem is related to working with files (e.g. opening and editing files), **does the problem happen for all files and projects or only some?** Does the problem happen only when working with local or remote files (e.g. on network drives), with files of a specific type (e.g. only JavaScript or Python files), with large files or files with very long lines, or with files in a specific encoding? Is there anything else special about the files you are using?
Include details about your configuration and environment:
* **Which version of capa are you using?** You can get the exact version by running `capa --version` in your terminal.
* **What's the name and version of the OS you're using**?
### Suggesting Enhancements
This section guides you through submitting an enhancement suggestion for capa, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion and find related suggestions.
Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](./ISSUE_TEMPLATE/feature_request.md), including the steps that you imagine you would take if the feature you're requesting existed.
#### Before Submitting An Enhancement Suggestion
* **Determine [which repository the enhancement should be suggested in](#capa-and-its-repositories).**
* **Perform a [cursory search](https://github.com/mandiant/capa/issues?q=is%3Aissue)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Enhancement Suggestion?
Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](#capa-and-its-repositories) your enhancement suggestion is related to, create an issue on that repository and provide the following information:
* **Use a clear and descriptive title** for the issue to identify the suggestion.
* **Provide a step-by-step description of the suggested enhancement** in as many details as possible.
* **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
* **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of capa which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
* **Explain why this enhancement would be useful** to most capa users and isn't something that can or should be implemented as an external tool that uses capa as a library.
* **Specify which version of capa you're using.** You can get the exact version by running `capa --version` in your terminal.
* **Specify the name and version of the OS you're using.**
### Your First Code Contribution
Unsure where to begin contributing to capa? You can start by looking through these `good-first-issue` and `rule-idea` issues:
* [good-first-issue](https://github.com/mandiant/capa/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) - issues which should only require a few lines of code, and a test or two.
* [rule-idea](https://github.com/mandiant/capa-rules/issues?q=is%3Aissue+is%3Aopen+label%3A%22rule+idea%22) - issues that describe potential new rule ideas.
Both issue lists are sorted by total number of comments. While not perfect, number of comments is a reasonable proxy for impact a given change will have.
#### Local development
capa and all its resources can be developed locally.
For instructions on how to do this, see the "Method 3" section of the [installation guide](https://github.com/mandiant/capa/blob/master/doc/installation.md).
### Pull Requests
The process described here has several goals:
- Maintain capa's quality
- Fix problems that are important to users
- Engage the community in working toward the best possible capa
- Enable a sustainable system for capa's maintainers to review contributions
Please follow these steps to have your contribution considered by the maintainers:
0. Sign the [Contributor License Agreement](#contributor-license-agreement)
1. Follow the [styleguides](#styleguides)
2. Update the CHANGELOG and add tests and documentation. In case they are not needed, indicate it in [the PR template](pull_request_template.md).
3. After you submit your pull request, verify that all [status checks](https://help.github.com/articles/about-status-checks/) are passing <details><summary>What if the status checks are failing? </summary>If a status check is failing, and you believe that the failure is unrelated to your change, please leave a comment on the pull request explaining why you believe the failure is unrelated. A maintainer will re-run the status check for you. If we conclude that the failure was a false positive, then we will open an issue to track that problem with our status check suite.</details>
While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted.
### Contributor License Agreement
Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution,
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Styleguides
### Git Commit Messages
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Prefix the first line with the component in question ("rules: ..." or "render: ...")
* Reference issues and pull requests liberally after the first line
### Python Styleguide
All Python code must adhere to the style guide used by capa:
1. [PEP8](https://www.python.org/dev/peps/pep-0008/), with clarifications from
2. [Willi's style guide](https://docs.google.com/document/d/1iRpeg-w4DtibwytUyC_dDT7IGhNGBP25-nQfuBa-Fyk/edit?usp=sharing), formatted with
3. [isort](https://pypi.org/project/isort/) (with line width 120 and ordered by line length), and formatted with
4. [black](https://github.com/psf/black) (with line width 120), and formatted with
5. [dos2unix](https://linux.die.net/man/1/dos2unix)
Our CI pipeline will reformat and enforce the Python styleguide.
### Rules Styleguide
All (non-nursery) capa rules must:
1. pass the [linter](https://github.com/mandiant/capa/blob/master/scripts/lint.py), and
2. be formatted with [capafmt](https://github.com/mandiant/capa/blob/master/scripts/capafmt.py)
This ensures that all rules meet the same minimum level of quality and are structured in a consistent way.
Our CI pipeline will reformat and enforce the capa rules styleguide.

View File

@@ -1,47 +1,47 @@
---
name: Bug report
about: Create a report to help us improve
---
<!--
# Is your bug report related to capa rules (for example a false positive)?
We use sybmodules to separate code, rules and test data. If your issue is related to capa rules, please report it at https://github.com/fireeye/capa-rules/issues.
# Have you checked that your issue isn't already filed?
Please search if there is a similar issue at https://github.com/fireeye/capa/issues. If there is already a similar issue, please add more details there instead of opening a new one.
# Have you read capa's Code of Conduct?
By filing an Issue, you are expected to comply with it, including treating everyone with respect: https://github.com/fireeye/capa/blob/master/.github/CODE_OF_CONDUCT.md
# Have you read capa's CONTRIBUTING guide?
It contains helpful information about how to contribute to capa. Check https://github.com/fireeye/capa/blob/master/.github/CONTRIBUTING.md#reporting-bugs
-->
### Description
<!-- Description of the issue -->
### Steps to Reproduce
<!-- 1. First Step -->
<!-- 2. Second Step -->
<!-- 3. and so on… -->
**Expected behavior:**
<!-- What you expect to happen -->
**Actual behavior:**
<!-- What actually happens -->
### Versions
<!-- You can get this information from copy and pasting the output of `capa --version` from the command line.
Please specify the component you're using (e.g. standalone tool or IDA Pro integration) and your Python version.
Also, please include the OS and what version of the OS you're running. -->
### Additional Information
<!-- Any additional information, configuration or data that might be necessary to reproduce the issue. -->
---
name: Bug report
about: Create a report to help us improve
---
<!--
# Is your bug report related to capa rules (for example a false positive)?
We use submodules to separate code, rules and test data. If your issue is related to capa rules, please report it at https://github.com/mandiant/capa-rules/issues.
# Have you checked that your issue isn't already filed?
Please search if there is a similar issue at https://github.com/mandiant/capa/issues. If there is already a similar issue, please add more details there instead of opening a new one.
# Have you read capa's Code of Conduct?
By filing an Issue, you are expected to comply with it, including treating everyone with respect: https://github.com/mandiant/capa/blob/master/.github/CODE_OF_CONDUCT.md
# Have you read capa's CONTRIBUTING guide?
It contains helpful information about how to contribute to capa. Check https://github.com/mandiant/capa/blob/master/.github/CONTRIBUTING.md#reporting-bugs
-->
### Description
<!-- Description of the issue -->
### Steps to Reproduce
<!-- 1. First Step -->
<!-- 2. Second Step -->
<!-- 3. and so on… -->
**Expected behavior:**
<!-- What you expect to happen -->
**Actual behavior:**
<!-- What actually happens -->
### Versions
<!-- You can get this information from copy and pasting the output of `capa --version` from the command line.
Please specify the component you're using (e.g. standalone tool or IDA Pro integration) and your Python version.
Also, please include the OS and what version of the OS you're running. -->
### Additional Information
<!-- Any additional information, configuration or data that might be necessary to reproduce the issue. -->

View File

@@ -1,35 +1,35 @@
---
name: Feature request
about: Suggest an idea for capa
---
<!--
# Is your issue related to capa rules (for example an idea for a new rule)?
We use sybmodules to separate code, rules and test data. If your issue is related to capa rules, please report it at https://github.com/fireeye/capa-rules/issues.
# Have you checked that your issue isn't already filed?
Please search if there is a similar issue at https://github.com/fireeye/capa/issues. If there is already a similar issue, please add more details there instead of opening a new one.
# Have you read capa's Code of Conduct?
By filing an Issue, you are expected to comply with it, including treating everyone with respect: https://github.com/fireeye/capa/blob/master/.github/CODE_OF_CONDUCT.md
# Have you read capa's CONTRIBUTING guide?
It contains helpful information about how to contribute to capa. Check https://github.com/fireeye/capa/blob/master/.github/CONTRIBUTING.md#suggesting-enhancements
-->
### Summary
<!-- One paragraph explanation of the feature. -->
### Motivation
<!-- Why are we doing this? What use cases does it support? What is the expected outcome? -->
### Describe alternatives you've considered
<!-- A clear and concise description of the alternative solutions you've considered. -->
## Additional context
<!-- Add any other context or screenshots about the feature request here. -->
---
name: Feature request
about: Suggest an idea for capa
---
<!--
# Is your issue related to capa rules (for example an idea for a new rule)?
We use submodules to separate code, rules and test data. If your issue is related to capa rules, please report it at https://github.com/mandiant/capa-rules/issues.
# Have you checked that your issue isn't already filed?
Please search if there is a similar issue at https://github.com/mandiant/capa/issues. If there is already a similar issue, please add more details there instead of opening a new one.
# Have you read capa's Code of Conduct?
By filing an Issue, you are expected to comply with it, including treating everyone with respect: https://github.com/mandiant/capa/blob/master/.github/CODE_OF_CONDUCT.md
# Have you read capa's CONTRIBUTING guide?
It contains helpful information about how to contribute to capa. Check https://github.com/mandiant/capa/blob/master/.github/CONTRIBUTING.md#suggesting-enhancements
-->
### Summary
<!-- One paragraph explanation of the feature. -->
### Motivation
<!-- Why are we doing this? What use cases does it support? What is the expected outcome? -->
### Describe alternatives you've considered
<!-- A clear and concise description of the alternative solutions you've considered. -->
## Additional context
<!-- Add any other context or screenshots about the feature request here. -->

BIN
.github/capa-explorer-logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
.github/capa-ida.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 KiB

6
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"

41
.github/flake8.ini vendored Normal file
View File

@@ -0,0 +1,41 @@
[flake8]
max-line-length = 120
extend-ignore =
# E203: whitespace before ':' (black does this)
E203,
# F401: `foo` imported but unused (prefer ruff)
F401,
# F811 Redefinition of unused `foo` (prefer ruff)
F811,
# E501 line too long (prefer black)
E501,
# B010 Do not call setattr with a constant attribute value
B010,
# G200 Logging statement uses exception in arguments
G200,
# SIM102 Use a single if-statement instead of nested if-statements
# doesn't provide a space for commenting or logical separation of conditions
SIM102,
# SIM114 Use logical or and a single body
# makes logic trees too complex
SIM114,
# SIM117 Use 'with Foo, Bar:' instead of multiple with statements
# makes lines too long
SIM117
per-file-ignores =
# T201 print found.
#
# scripts are meant to print output
scripts/*: T201
# capa.exe is meant to print output
capa/main.py: T201
# IDA tests emit results to output window so need to print
tests/test_ida_features.py: T201
# utility used to find the Binary Ninja API via invoking python.exe
capa/features/extractors/binja/find_binja_api.py: T201
copyright-check = True
copyright-min-file-size = 1
copyright-regexp = Copyright \(C\) 2023 Mandiant, Inc. All Rights Reserved.

91
.github/mypy/mypy.ini vendored Normal file
View File

@@ -0,0 +1,91 @@
[mypy]
[mypy-halo.*]
ignore_missing_imports = True
[mypy-tqdm.*]
ignore_missing_imports = True
[mypy-ruamel.*]
ignore_missing_imports = True
[mypy-networkx.*]
ignore_missing_imports = True
[mypy-pefile.*]
ignore_missing_imports = True
[mypy-viv_utils.*]
ignore_missing_imports = True
[mypy-flirt.*]
ignore_missing_imports = True
[mypy-lief.*]
ignore_missing_imports = True
[mypy-idc.*]
ignore_missing_imports = True
[mypy-vivisect.*]
ignore_missing_imports = True
[mypy-envi.*]
ignore_missing_imports = True
[mypy-PE.*]
ignore_missing_imports = True
[mypy-idaapi.*]
ignore_missing_imports = True
[mypy-idautils.*]
ignore_missing_imports = True
[mypy-ida_auto.*]
ignore_missing_imports = True
[mypy-ida_bytes.*]
ignore_missing_imports = True
[mypy-ida_nalt.*]
ignore_missing_imports = True
[mypy-ida_kernwin.*]
ignore_missing_imports = True
[mypy-ida_settings.*]
ignore_missing_imports = True
[mypy-ida_funcs.*]
ignore_missing_imports = True
[mypy-ida_loader.*]
ignore_missing_imports = True
[mypy-ida_segment.*]
ignore_missing_imports = True
[mypy-PyQt5.*]
ignore_missing_imports = True
[mypy-binaryninja.*]
ignore_missing_imports = True
[mypy-pytest.*]
ignore_missing_imports = True
[mypy-devtools.*]
ignore_missing_imports = True
[mypy-elftools.*]
ignore_missing_imports = True
[mypy-dncil.*]
ignore_missing_imports = True
[mypy-netnode.*]
ignore_missing_imports = True
[mypy-ghidra.*]
ignore_missing_imports = True

22
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,22 @@
<!--
Thank you for contributing to capa! <3
Please read capa's CONTRIBUTING guide if you haven't done so already.
It contains helpful information about how to contribute to capa. Check https://github.com/mandiant/capa/blob/master/.github/CONTRIBUTING.md
Please describe the changes in this pull request (PR). Include your motivation and context to help us review.
Please mention the issue your PR addresses (if any):
closes #issue_number
-->
### Checklist
<!-- CHANGELOG.md has a `master (unreleased)` section. Please add bug fixes, new features, breaking changes and anything else you think is worthwhile mentioning in the release notes to this file. -->
- [ ] No CHANGELOG update needed
<!-- Tests prove that your fix/work as expected and ensure it doesn't break on the feature. -->
- [ ] No new tests needed
<!-- Please help us keeping capa documentation up-to-date -->
- [ ] No documentation update needed

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2020 FireEye, Inc. All Rights Reserved.
# Copyright (C) 2020 Mandiant, Inc. All Rights Reserved.
from PyInstaller.utils.hooks import copy_metadata
@@ -13,3 +13,173 @@ from PyInstaller.utils.hooks import copy_metadata
#
# ref: https://github.com/pyinstaller/pyinstaller/issues/1713#issuecomment-162682084
datas = copy_metadata("vivisect")
excludedimports = [
# viv gui requires these heavy libraries,
# but viv as a library doesn't.
# they shouldn't be installed in our configuration,
# but we'll ensure they don't slip in here (such as on developers' systems).
"PyQt5",
"qt5",
"pyqtwebengine",
# the above are imported by these viv modules.
# so really, we'd want to exclude these submodules of viv.
# but i dont think this works.
"vqt",
"vdb.qt",
"envi.qt",
# unused by capa
"pyasn1",
]
hiddenimports = [
# vivisect does manual/runtime importing of its modules,
# so declare the things that could be imported here.
"vivisect",
"vivisect.analysis",
"vivisect.analysis.amd64",
"vivisect.analysis.amd64.emulation",
"vivisect.analysis.amd64.golang",
"vivisect.analysis.crypto",
"vivisect.analysis.crypto.constants",
"vivisect.analysis.elf",
"vivisect.analysis.elf.elfplt",
"vivisect.analysis.elf.elfplt_late",
"vivisect.analysis.elf.libc_start_main",
"vivisect.analysis.generic",
"vivisect.analysis.generic.codeblocks",
"vivisect.analysis.generic.emucode",
"vivisect.analysis.generic.entrypoints",
"vivisect.analysis.generic.funcentries",
"vivisect.analysis.generic.impapi",
"vivisect.analysis.generic.linker",
"vivisect.analysis.generic.mkpointers",
"vivisect.analysis.generic.noret",
"vivisect.analysis.generic.pointers",
"vivisect.analysis.generic.pointertables",
"vivisect.analysis.generic.relocations",
"vivisect.analysis.generic.strconst",
"vivisect.analysis.generic.switchcase",
"vivisect.analysis.generic.symswitchcase",
"vivisect.analysis.generic.thunks",
"vivisect.analysis.i386",
"vivisect.analysis.i386.calling",
"vivisect.analysis.i386.golang",
"vivisect.analysis.i386.importcalls",
"vivisect.analysis.i386.instrhook",
"vivisect.analysis.i386.thunk_reg",
"vivisect.analysis.ms",
"vivisect.analysis.ms.hotpatch",
"vivisect.analysis.ms.localhints",
"vivisect.analysis.ms.msvc",
"vivisect.analysis.ms.msvcfunc",
"vivisect.analysis.ms.vftables",
"vivisect.analysis.pe",
"vivisect.impapi.posix.amd64",
"vivisect.impapi.posix.i386",
"vivisect.impapi.windows",
"vivisect.impapi.windows.advapi_32",
"vivisect.impapi.windows.advapi_64",
"vivisect.impapi.windows.amd64",
"vivisect.impapi.windows.gdi_32",
"vivisect.impapi.windows.gdi_64",
"vivisect.impapi.windows.i386",
"vivisect.impapi.windows.kernel_32",
"vivisect.impapi.windows.kernel_64",
"vivisect.impapi.windows.msvcr100_32",
"vivisect.impapi.windows.msvcr100_64",
"vivisect.impapi.windows.msvcr110_32",
"vivisect.impapi.windows.msvcr110_64",
"vivisect.impapi.windows.msvcr120_32",
"vivisect.impapi.windows.msvcr120_64",
"vivisect.impapi.windows.msvcr71_32",
"vivisect.impapi.windows.msvcr80_32",
"vivisect.impapi.windows.msvcr80_64",
"vivisect.impapi.windows.msvcr90_32",
"vivisect.impapi.windows.msvcr90_64",
"vivisect.impapi.windows.msvcrt_32",
"vivisect.impapi.windows.msvcrt_64",
"vivisect.impapi.windows.ntdll_32",
"vivisect.impapi.windows.ntdll_64",
"vivisect.impapi.windows.ole_32",
"vivisect.impapi.windows.ole_64",
"vivisect.impapi.windows.rpcrt4_32",
"vivisect.impapi.windows.rpcrt4_64",
"vivisect.impapi.windows.shell_32",
"vivisect.impapi.windows.shell_64",
"vivisect.impapi.windows.user_32",
"vivisect.impapi.windows.user_64",
"vivisect.impapi.windows.ws2plus_32",
"vivisect.impapi.windows.ws2plus_64",
"vivisect.impapi.winkern",
"vivisect.impapi.winkern.i386",
"vivisect.impapi.winkern.amd64",
"vivisect.parsers.blob",
"vivisect.parsers.elf",
"vivisect.parsers.ihex",
"vivisect.parsers.macho",
"vivisect.parsers.pe",
"vivisect.storage",
"vivisect.storage.basicfile",
"vstruct.constants",
"vstruct.constants.ntstatus",
"vstruct.defs",
"vstruct.defs.arm7",
"vstruct.defs.bmp",
"vstruct.defs.dns",
"vstruct.defs.elf",
"vstruct.defs.gif",
"vstruct.defs.ihex",
"vstruct.defs.inet",
"vstruct.defs.java",
"vstruct.defs.kdcom",
"vstruct.defs.macho",
"vstruct.defs.macho.const",
"vstruct.defs.macho.fat",
"vstruct.defs.macho.loader",
"vstruct.defs.macho.stabs",
"vstruct.defs.minidump",
"vstruct.defs.pcap",
"vstruct.defs.pe",
"vstruct.defs.pptp",
"vstruct.defs.rar",
"vstruct.defs.swf",
"vstruct.defs.win32",
"vstruct.defs.windows",
"vstruct.defs.windows.win_5_1_i386",
"vstruct.defs.windows.win_5_1_i386.ntdll",
"vstruct.defs.windows.win_5_1_i386.ntoskrnl",
"vstruct.defs.windows.win_5_1_i386.win32k",
"vstruct.defs.windows.win_5_2_i386",
"vstruct.defs.windows.win_5_2_i386.ntdll",
"vstruct.defs.windows.win_5_2_i386.ntoskrnl",
"vstruct.defs.windows.win_5_2_i386.win32k",
"vstruct.defs.windows.win_6_1_amd64",
"vstruct.defs.windows.win_6_1_amd64.ntdll",
"vstruct.defs.windows.win_6_1_amd64.ntoskrnl",
"vstruct.defs.windows.win_6_1_amd64.win32k",
"vstruct.defs.windows.win_6_1_i386",
"vstruct.defs.windows.win_6_1_i386.ntdll",
"vstruct.defs.windows.win_6_1_i386.ntoskrnl",
"vstruct.defs.windows.win_6_1_i386.win32k",
"vstruct.defs.windows.win_6_1_wow64",
"vstruct.defs.windows.win_6_1_wow64.ntdll",
"vstruct.defs.windows.win_6_2_amd64",
"vstruct.defs.windows.win_6_2_amd64.ntdll",
"vstruct.defs.windows.win_6_2_amd64.ntoskrnl",
"vstruct.defs.windows.win_6_2_amd64.win32k",
"vstruct.defs.windows.win_6_2_i386",
"vstruct.defs.windows.win_6_2_i386.ntdll",
"vstruct.defs.windows.win_6_2_i386.ntoskrnl",
"vstruct.defs.windows.win_6_2_i386.win32k",
"vstruct.defs.windows.win_6_2_wow64",
"vstruct.defs.windows.win_6_2_wow64.ntdll",
"vstruct.defs.windows.win_6_3_amd64",
"vstruct.defs.windows.win_6_3_amd64.ntdll",
"vstruct.defs.windows.win_6_3_amd64.ntoskrnl",
"vstruct.defs.windows.win_6_3_i386",
"vstruct.defs.windows.win_6_3_i386.ntdll",
"vstruct.defs.windows.win_6_3_i386.ntoskrnl",
"vstruct.defs.windows.win_6_3_wow64",
"vstruct.defs.windows.win_6_3_wow64.ntdll",
]

View File

@@ -1,175 +1,41 @@
# -*- mode: python -*-
# Copyright (C) 2020 FireEye, Inc. All Rights Reserved.
# Copyright (C) 2020 Mandiant, Inc. All Rights Reserved.
import os.path
import subprocess
import wcwidth
# when invoking pyinstaller from the project root,
# this gets run from the project root.
with open('./capa/version.py', 'wb') as f:
# git output will look like:
#
# tags/v1.0.0-0-g3af38dc
# ------- tag
# - commits since
# g------- git hash fragment
version = (subprocess.check_output(["git", "describe", "--always", "--tags", "--long"])
.strip()
.replace("tags/", ""))
f.write("__version__ = '%s'" % version)
a = Analysis(
# when invoking pyinstaller from the project root,
# this gets invoked from the directory of the spec file,
# i.e. ./.github/pyinstaller
['../../capa/main.py'],
pathex=['capa'],
["../../capa/main.py"],
pathex=["capa"],
binaries=None,
datas=[
# when invoking pyinstaller from the project root,
# this gets invoked from the directory of the spec file,
# i.e. ./.github/pyinstaller
('../../rules', 'rules'),
("../../assets", "assets"),
("../../rules", "rules"),
("../../sigs", "sigs"),
("../../cache", "cache"),
# capa.render.default uses tabulate that depends on wcwidth.
# it seems wcwidth uses a json file `version.json`
# and this doesn't get picked up by pyinstaller automatically.
# so we manually embed the wcwidth resources here.
#
# ref: https://stackoverflow.com/a/62278462/87207
(os.path.dirname(wcwidth.__file__), 'wcwidth')
],
hiddenimports=[
# vivisect does manual/runtime importing of its modules,
# so declare the things that could be imported here.
"pycparser",
"vivisect",
"vivisect.analysis",
"vivisect.analysis.amd64",
"vivisect.analysis.amd64",
"vivisect.analysis.amd64.emulation",
"vivisect.analysis.amd64.golang",
"vivisect.analysis.crypto",
"vivisect.analysis.crypto",
"vivisect.analysis.crypto.constants",
"vivisect.analysis.elf",
"vivisect.analysis.elf",
"vivisect.analysis.elf.elfplt",
"vivisect.analysis.elf.libc_start_main",
"vivisect.analysis.generic",
"vivisect.analysis.generic",
"vivisect.analysis.generic.codeblocks",
"vivisect.analysis.generic.emucode",
"vivisect.analysis.generic.entrypoints",
"vivisect.analysis.generic.funcentries",
"vivisect.analysis.generic.impapi",
"vivisect.analysis.generic.mkpointers",
"vivisect.analysis.generic.pointers",
"vivisect.analysis.generic.pointertables",
"vivisect.analysis.generic.relocations",
"vivisect.analysis.generic.strconst",
"vivisect.analysis.generic.switchcase",
"vivisect.analysis.generic.thunks",
"vivisect.analysis.i386",
"vivisect.analysis.i386",
"vivisect.analysis.i386.calling",
"vivisect.analysis.i386.golang",
"vivisect.analysis.i386.importcalls",
"vivisect.analysis.i386.instrhook",
"vivisect.analysis.i386.thunk_bx",
"vivisect.analysis.ms",
"vivisect.analysis.ms",
"vivisect.analysis.ms.hotpatch",
"vivisect.analysis.ms.localhints",
"vivisect.analysis.ms.msvc",
"vivisect.analysis.ms.msvcfunc",
"vivisect.analysis.ms.vftables",
"vivisect.analysis.pe",
"vivisect.impapi.posix.amd64",
"vivisect.impapi.posix.i386",
"vivisect.impapi.windows",
"vivisect.impapi.windows.amd64",
"vivisect.impapi.windows.i386",
"vivisect.parsers.blob",
"vivisect.parsers.elf",
"vivisect.parsers.ihex",
"vivisect.parsers.macho",
"vivisect.parsers.parse_pe",
"vivisect.parsers.utils",
"vivisect.storage",
"vivisect.storage.basicfile",
"vstruct.constants",
"vstruct.constants.ntstatus",
"vstruct.defs",
"vstruct.defs.arm7",
"vstruct.defs.bmp",
"vstruct.defs.dns",
"vstruct.defs.elf",
"vstruct.defs.gif",
"vstruct.defs.ihex",
"vstruct.defs.inet",
"vstruct.defs.java",
"vstruct.defs.kdcom",
"vstruct.defs.macho",
"vstruct.defs.macho.const",
"vstruct.defs.macho.fat",
"vstruct.defs.macho.loader",
"vstruct.defs.macho.stabs",
"vstruct.defs.minidump",
"vstruct.defs.pcap",
"vstruct.defs.pe",
"vstruct.defs.pptp",
"vstruct.defs.rar",
"vstruct.defs.swf",
"vstruct.defs.win32",
"vstruct.defs.windows",
"vstruct.defs.windows.win_5_1_i386",
"vstruct.defs.windows.win_5_1_i386.ntdll",
"vstruct.defs.windows.win_5_1_i386.ntoskrnl",
"vstruct.defs.windows.win_5_1_i386.win32k",
"vstruct.defs.windows.win_5_2_i386",
"vstruct.defs.windows.win_5_2_i386.ntdll",
"vstruct.defs.windows.win_5_2_i386.ntoskrnl",
"vstruct.defs.windows.win_5_2_i386.win32k",
"vstruct.defs.windows.win_6_1_amd64",
"vstruct.defs.windows.win_6_1_amd64.ntdll",
"vstruct.defs.windows.win_6_1_amd64.ntoskrnl",
"vstruct.defs.windows.win_6_1_amd64.win32k",
"vstruct.defs.windows.win_6_1_i386",
"vstruct.defs.windows.win_6_1_i386.ntdll",
"vstruct.defs.windows.win_6_1_i386.ntoskrnl",
"vstruct.defs.windows.win_6_1_i386.win32k",
"vstruct.defs.windows.win_6_1_wow64",
"vstruct.defs.windows.win_6_1_wow64.ntdll",
"vstruct.defs.windows.win_6_2_amd64",
"vstruct.defs.windows.win_6_2_amd64.ntdll",
"vstruct.defs.windows.win_6_2_amd64.ntoskrnl",
"vstruct.defs.windows.win_6_2_amd64.win32k",
"vstruct.defs.windows.win_6_2_i386",
"vstruct.defs.windows.win_6_2_i386.ntdll",
"vstruct.defs.windows.win_6_2_i386.ntoskrnl",
"vstruct.defs.windows.win_6_2_i386.win32k",
"vstruct.defs.windows.win_6_2_wow64",
"vstruct.defs.windows.win_6_2_wow64.ntdll",
"vstruct.defs.windows.win_6_3_amd64",
"vstruct.defs.windows.win_6_3_amd64.ntdll",
"vstruct.defs.windows.win_6_3_amd64.ntoskrnl",
"vstruct.defs.windows.win_6_3_i386",
"vstruct.defs.windows.win_6_3_i386.ntdll",
"vstruct.defs.windows.win_6_3_i386.ntoskrnl",
"vstruct.defs.windows.win_6_3_wow64",
"vstruct.defs.windows.win_6_3_wow64.ntdll",
(os.path.dirname(wcwidth.__file__), "wcwidth"),
],
# when invoking pyinstaller from the project root,
# this gets run from the project root.
hookspath=['.github/pyinstaller/hooks'],
hookspath=[".github/pyinstaller/hooks"],
runtime_hooks=None,
excludes=[
# ignore packages that would otherwise be bundled with the .exe.
# review: build/pyinstaller/xref-pyinstaller.html
# we don't do any GUI stuff, so ignore these modules
"tkinter",
"_tkinter",
@@ -179,35 +45,52 @@ a = Analysis(
# since we don't spawn a notebook, we can safely remove these.
"IPython",
"ipywidgets",
])
# these are pulled in by networkx
# but we don't need to compute the strongly connected components.
"numpy",
"scipy",
"matplotlib",
"pandas",
"pytest",
# deps from viv that we don't use.
# this duplicates the entries in `hook-vivisect`,
# but works better this way.
"vqt",
"vdb.qt",
"envi.qt",
"PyQt5",
"qt5",
"pyqtwebengine",
"pyasn1",
"binaryninja",
],
)
a.binaries = a.binaries - TOC([
('tcl85.dll', None, None),
('tk85.dll', None, None),
('_tkinter', None, None)])
a.binaries = a.binaries - TOC([("tcl85.dll", None, None), ("tk85.dll", None, None), ("_tkinter", None, None)])
pyz = PYZ(a.pure, a.zipped_data)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
exclude_binaries=False,
name='capa',
icon='logo.ico',
debug=False,
strip=None,
upx=True,
console=True )
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
exclude_binaries=False,
name="capa",
icon="logo.ico",
debug=False,
strip=False,
upx=True,
console=True,
)
# enable the following to debug the contents of the .exe
#
#coll = COLLECT(exe,
# coll = COLLECT(exe,
# a.binaries,
# a.zipfiles,
# a.datas,
# strip=None,
# upx=True,
# name='capa-dat')

43
.github/ruff.toml vendored Normal file
View File

@@ -0,0 +1,43 @@
# Enable the pycodestyle (`E`) and Pyflakes (`F`) rules by default.
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
# McCabe complexity (`C901`) by default.
select = ["E", "F"]
# Allow autofix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []
# E402 module level import not at top of file
# E722 do not use bare 'except'
# E501 line too long
ignore = ["E402", "E722", "E501"]
line-length = 120
exclude = [
# Exclude a variety of commonly ignored directories.
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".mypy_cache",
".nox",
".pants.d",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
# protobuf generated files
"*_pb2.py",
"*_pb2.pyi"
]

10
.github/tox.ini vendored
View File

@@ -1,10 +0,0 @@
[pycodestyle]
; E402: module level import not at top of file
; W503: line break before binary operator
; E231 missing whitespace after ',' (emitted by black)
; E203 whitespace before ':' (emitted by black)
ignore = E402,W503,E203,E231
max-line-length = 160
statistics = True
count = True
exclude = .*

View File

@@ -1,77 +1,135 @@
name: build
on:
release:
types: [created, edited]
jobs:
build:
name: PyInstaller for ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-16.04
# use old linux so that the shared library versioning is more portable
artifact_name: capa
asset_name: linux
- os: windows-latest
artifact_name: capa.exe
asset_name: windows
- os: macos-latest
artifact_name: capa
asset_name: macos
steps:
- name: Checkout capa
uses: actions/checkout@v2
with:
submodules: true
- name: Set up Python 2.7
uses: actions/setup-python@v2
with:
python-version: 2.7
- name: Install PyInstaller
# pyinstaller 4 doesn't support Python 2.7
run: pip install 'pyinstaller==3.*'
- name: Install capa
run: pip install -e .
- name: Build standalone executable
run: pyinstaller .github/pyinstaller/pyinstaller.spec
- name: Does it run?
run: dist/capa "tests/data/Practical Malware Analysis Lab 01-01.dll_"
- uses: actions/upload-artifact@v2
with:
name: ${{ matrix.asset_name }}
path: dist/${{ matrix.artifact_name }}
zip:
name: zip ${{ matrix.asset_name }}
runs-on: ubuntu-latest
needs: build
strategy:
matrix:
include:
- asset_name: linux
artifact_name: capa
- asset_name: windows
artifact_name: capa.exe
- asset_name: macos
artifact_name: capa
steps:
- name: Download ${{ matrix.asset_name }}
uses: actions/download-artifact@v2
with:
name: ${{ matrix.asset_name }}
- name: Set executable flag
run: chmod +x ${{ matrix.artifact_name }}
- name: Set zip name
run: echo ::set-env name=zip_name::capa-${GITHUB_REF#refs/tags/}-${{ matrix.asset_name }}.zip
- name: Zip ${{ matrix.artifact_name }} into ${{ env.zip_name }}
run: zip ${{ env.zip_name }} ${{ matrix.artifact_name }}
- name: Upload ${{ env.zip_name }} to GH Release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN}}
file: ${{ env.zip_name }}
tag: ${{ github.ref }}
name: build
on:
pull_request:
branches: [ master ]
release:
types: [edited, published]
permissions:
contents: write
jobs:
build:
name: PyInstaller for ${{ matrix.os }} / Py ${{ matrix.python_version }}
runs-on: ${{ matrix.os }}
strategy:
# set to false for debugging
fail-fast: true
matrix:
# using Python 3.8 to support running across multiple operating systems including Windows 7
include:
- os: ubuntu-20.04
# use old linux so that the shared library versioning is more portable
artifact_name: capa
asset_name: linux
python_version: 3.8
- os: ubuntu-20.04
artifact_name: capa
asset_name: linux-py311
python_version: 3.11
- os: windows-2019
artifact_name: capa.exe
asset_name: windows
python_version: 3.8
- os: macos-11
# use older macOS for assumed better portability
artifact_name: capa
asset_name: macos
python_version: 3.8
steps:
- name: Checkout capa
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
with:
submodules: true
- name: Set up Python ${{ matrix.python_version }}
uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # v4.5.0
with:
python-version: ${{ matrix.python_version }}
- if: matrix.os == 'ubuntu-20.04'
run: sudo apt-get install -y libyaml-dev
- name: Upgrade pip, setuptools
run: python -m pip install --upgrade pip setuptools
- name: Install capa with build requirements
run: pip install -e .[build]
- name: Cache the rule set
run: python ./scripts/cache-ruleset.py ./rules/ ./cache/
- name: Build standalone executable
run: pyinstaller --log-level DEBUG .github/pyinstaller/pyinstaller.spec
- name: Does it run (PE)?
run: dist/capa "tests/data/Practical Malware Analysis Lab 01-01.dll_"
- name: Does it run (Shellcode)?
run: dist/capa "tests/data/499c2a85f6e8142c3f48d4251c9c7cd6.raw32"
- name: Does it run (ELF)?
run: dist/capa "tests/data/7351f8a40c5450557b24622417fc478d.elf_"
- name: Does it run (CAPE)?
run: |
7z e "tests/data/dynamic/cape/v2.2/d46900384c78863420fb3e297d0a2f743cd2b6b3f7f82bf64059a168e07aceb7.json.gz"
dist/capa "d46900384c78863420fb3e297d0a2f743cd2b6b3f7f82bf64059a168e07aceb7.json"
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
name: ${{ matrix.asset_name }}
path: dist/${{ matrix.artifact_name }}
test_run:
name: Test run on ${{ matrix.os }} / ${{ matrix.asset_name }}
runs-on: ${{ matrix.os }}
needs: [build]
strategy:
matrix:
include:
# OSs not already tested above
- os: ubuntu-22.04
artifact_name: capa
asset_name: linux
- os: ubuntu-22.04
artifact_name: capa
asset_name: linux-py311
- os: windows-2022
artifact_name: capa.exe
asset_name: windows
steps:
- name: Download ${{ matrix.asset_name }}
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with:
name: ${{ matrix.asset_name }}
- name: Set executable flag
if: matrix.os != 'windows-2022'
run: chmod +x ${{ matrix.artifact_name }}
- name: Run capa
run: ./${{ matrix.artifact_name }} -h
zip_and_upload:
# upload zipped binaries to Release page
if: github.event_name == 'release'
name: zip and upload ${{ matrix.asset_name }}
runs-on: ubuntu-20.04
needs: [build]
strategy:
matrix:
include:
- asset_name: linux
artifact_name: capa
- asset_name: linux-py311
artifact_name: capa
- asset_name: windows
artifact_name: capa.exe
- asset_name: macos
artifact_name: capa
steps:
- name: Download ${{ matrix.asset_name }}
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with:
name: ${{ matrix.asset_name }}
- name: Set executable flag
run: chmod +x ${{ matrix.artifact_name }}
- name: Set zip name
run: echo "zip_name=capa-${GITHUB_REF#refs/tags/}-${{ matrix.asset_name }}.zip" >> $GITHUB_ENV
- name: Zip ${{ matrix.artifact_name }} into ${{ env.zip_name }}
run: zip ${{ env.zip_name }} ${{ matrix.artifact_name }}
- name: Upload ${{ env.zip_name }} to GH Release
uses: svenstaro/upload-release-action@2728235f7dc9ff598bd86ce3c274b74f802d2208 # v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN}}
file: ${{ env.zip_name }}
tag: ${{ github.ref }}

43
.github/workflows/changelog.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: changelog
on:
# We need pull_request_target instead of pull_request because a write
# repository token is needed to add a review to a PR. DO NOT BUILD
# OR RUN UNTRUSTED CODE FROM PRs IN THIS ACTION
pull_request_target:
types: [opened, edited, synchronize]
permissions: read-all
jobs:
check_changelog:
# no need to check for dependency updates via dependabot
if: github.actor != 'dependabot[bot]' && github.actor != 'dependabot-preview[bot]'
runs-on: ubuntu-20.04
env:
NO_CHANGELOG: '[x] No CHANGELOG update needed'
steps:
- name: Get changed files
id: files
uses: Ana06/get-changed-files@e0c398b7065a8d84700c471b6afc4116d1ba4e96 # v2.2.0
- name: check changelog updated
id: changelog_updated
env:
PR_BODY: ${{ github.event.pull_request.body }}
FILES: ${{ steps.files.outputs.modified }}
run: |
echo $FILES | grep -qF 'CHANGELOG.md' || echo $PR_BODY | grep -qiF "$NO_CHANGELOG"
- name: Reject pull request if no CHANGELOG update
if: ${{ always() && steps.changelog_updated.outcome == 'failure' }}
uses: Ana06/automatic-pull-request-review@0cf4e8a17ba79344ed3fdd7fed6dd0311d08a9d4 # v0.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
event: REQUEST_CHANGES
body: "Please add bug fixes, new features, breaking changes and anything else you think is worthwhile mentioning to the `master (unreleased)` section of CHANGELOG.md. If no CHANGELOG update is needed add the following to the PR description: `${{ env.NO_CHANGELOG }}`"
allow_duplicate: false
- name: Dismiss previous review if CHANGELOG update
uses: Ana06/automatic-pull-request-review@0cf4e8a17ba79344ed3fdd7fed6dd0311d08a9d4 # v0.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
event: DISMISS
body: "CHANGELOG updated or no update needed, thanks! :smile:"

21
.github/workflows/pip-audit.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: PIP audit
on:
schedule:
- cron: '0 8 * * 1'
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
matrix:
python-version: ["3.11"]
steps:
- name: Check out repository code
uses: actions/checkout@v4
- uses: pypa/gh-action-pip-audit@v1.0.8
with:
inputs: .

41
.github/workflows/publish.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
# use PyPI trusted publishing, as described here:
# https://blog.trailofbits.com/2023/05/23/trusted-publishing-a-new-benchmark-for-packaging-security/
name: publish to pypi
on:
release:
types: [published]
permissions:
contents: write
jobs:
pypi-publish:
runs-on: ubuntu-latest
environment:
name: release
permissions:
id-token: write
steps:
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Set up Python
uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # v4.5.0
with:
python-version: '3.8'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[build]
- name: build package
run: |
python -m build
- name: upload package artifacts
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
path: dist/*
- name: publish package
uses: pypa/gh-action-pypi-publish@f5622bde02b04381239da3573277701ceca8f6a0 # release/v1
with:
skip-existing: true
verbose: true
print-hash: true

72
.github/workflows/scorecard.yml vendored Normal file
View File

@@ -0,0 +1,72 @@
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.
name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: '43 4 * * 3'
push:
branches: [ "master" ]
# Declare default permissions as read only.
permissions: read-all
jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write
# Uncomment the permissions below if installing in a private repository.
# contents: read
# actions: read
steps:
- name: "Checkout code"
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@99c53751e09b9529366343771cc321ec74e9bd3d # v2.0.6
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories:
# - `publish_results` will always be set to `false`, regardless
# of the value entered here.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@807578363a7869ca324a79039e6db9c843e0e100 # v2.1.27
with:
sarif_file: results.sarif

32
.github/workflows/tag.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: tag
on:
release:
types: [published]
permissions: read-all
jobs:
tag:
name: Tag capa rules
runs-on: ubuntu-20.04
steps:
- name: Checkout capa-rules
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
with:
repository: mandiant/capa-rules
token: ${{ secrets.CAPA_TOKEN }}
- name: Tag capa-rules
run: |
# user information is needed to create annotated tags (with a message)
git config user.email 'capa-dev@mandiant.com'
git config user.name 'Capa Bot'
name=${{ github.event.release.tag_name }}
git tag $name -m "https://github.com/mandiant/capa/releases/$name"
# TODO update branch name-major=${name%%.*}
- name: Push tag to capa-rules
uses: ad-m/github-push-action@0fafdd62b84042d49ec0cb92d9cac7f7ce4ec79e # master
with:
repository: mandiant/capa-rules
github_token: ${{ secrets.CAPA_TOKEN }}
tags: true

View File

@@ -6,63 +6,199 @@ on:
pull_request:
branches: [ master ]
permissions: read-all
# save workspaces to speed up testing
env:
CAPA_SAVE_WORKSPACE: "True"
jobs:
code_style:
runs-on: ubuntu-latest
changelog_format:
runs-on: ubuntu-20.04
steps:
- name: Checkout capa
uses: actions/checkout@v2
- name: Set up Python 3.8
uses: actions/setup-python@v2
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
# The sync GH action in capa-rules relies on a single '- *$' in the CHANGELOG file
- name: Ensure CHANGELOG has '- *$'
run: |
number=$(grep '\- *$' CHANGELOG.md | wc -l)
if [ $number != 1 ]; then exit 1; fi
code_style:
runs-on: ubuntu-20.04
steps:
- name: Checkout capa
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
# use latest available python to take advantage of best performance
- name: Set up Python 3.11
uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # v4.5.0
with:
python-version: 3.8
python-version: "3.11"
- name: Install dependencies
run: pip install 'isort==5.*' black
run: pip install -e .[dev]
- name: Lint with ruff
run: pre-commit run ruff
- name: Lint with isort
run: isort --profile black --length-sort --line-width 120 -c .
run: pre-commit run isort --show-diff-on-failure
- name: Lint with black
run: black -l 120 --check .
run: pre-commit run black --show-diff-on-failure
- name: Lint with flake8
run: pre-commit run flake8 --hook-stage manual
- name: Check types with mypy
run: pre-commit run mypy --hook-stage manual
rule_linter:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- name: Checkout capa with rules submodule
uses: actions/checkout@v2
- name: Checkout capa with submodules
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
with:
submodules: true
- name: Set up Python 3.8
uses: actions/setup-python@v2
submodules: recursive
- name: Set up Python 3.11
uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # v4.5.0
with:
python-version: 3.8
# We don't need vivisect, so we can install capa using Python3
python-version: "3.11"
- name: Install capa
run: pip install -e .
run: pip install -e .[dev]
- name: Run rule linter
run: python scripts/lint.py rules/
tests:
name: Tests in ${{ matrix.python }}
runs-on: ubuntu-latest
name: Tests in ${{ matrix.python-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
needs: [code_style, rule_linter]
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, windows-2019, macos-11]
# across all operating systems
python-version: ["3.8", "3.11"]
include:
- python: 2.7
- python: 3.6
- python: 3.7
- python: 3.8
- python: '3.9.0-alpha - 3.9.x' # Python latest
# on Ubuntu run these as well
- os: ubuntu-20.04
python-version: "3.8"
- os: ubuntu-20.04
python-version: "3.9"
- os: ubuntu-20.04
python-version: "3.10"
steps:
- name: Checkout capa with submodules
uses: actions/checkout@v2
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
with:
submodules: true
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v2
submodules: recursive
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # v4.5.0
with:
python-version: ${{ matrix.python }}
python-version: ${{ matrix.python-version }}
- name: Install pyyaml
if: matrix.os == 'ubuntu-20.04'
run: sudo apt-get install -y libyaml-dev
- name: Install capa
run: pip install -e .[dev]
- name: Run tests (fast)
# this set of tests runs about 80% of the cases in 20% of the time,
# and should catch most errors quickly.
run: pre-commit run pytest-fast --all-files --hook-stage manual
- name: Run tests
run: pytest tests/
run: pytest -v tests/
binja-tests:
name: Binary Ninja tests for ${{ matrix.python-version }}
env:
BN_SERIAL: ${{ secrets.BN_SERIAL }}
runs-on: ubuntu-20.04
needs: [tests]
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.11"]
steps:
- name: Checkout capa with submodules
# do only run if BN_SERIAL is available, have to do this in every step, see https://github.com/orgs/community/discussions/26726#discussioncomment-3253118
if: ${{ env.BN_SERIAL != 0 }}
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
with:
submodules: recursive
- name: Set up Python ${{ matrix.python-version }}
if: ${{ env.BN_SERIAL != 0 }}
uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # v4.5.0
with:
python-version: ${{ matrix.python-version }}
- name: Install pyyaml
if: ${{ env.BN_SERIAL != 0 }}
run: sudo apt-get install -y libyaml-dev
- name: Install capa
if: ${{ env.BN_SERIAL != 0 }}
run: pip install -e .[dev]
- name: install Binary Ninja
if: ${{ env.BN_SERIAL != 0 }}
run: |
mkdir ./.github/binja
curl "https://raw.githubusercontent.com/Vector35/binaryninja-api/6812c97/scripts/download_headless.py" -o ./.github/binja/download_headless.py
python ./.github/binja/download_headless.py --serial ${{ env.BN_SERIAL }} --output .github/binja/BinaryNinja-headless.zip
unzip .github/binja/BinaryNinja-headless.zip -d .github/binja/
python .github/binja/binaryninja/scripts/install_api.py --install-on-root --silent
- name: Run tests
if: ${{ env.BN_SERIAL != 0 }}
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: [tests]
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "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: ["3.0.0"]
steps:
- name: Checkout capa with submodules
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
with:
submodules: true
- 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@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3
with:
distribution: 'temurin'
java-version: ${{ matrix.java-version }}
- 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_${{ 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
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/
gradle -p ./.github/ghidrathon/Ghidrathon-${{ matrix.ghidrathon-version }}/ -PGHIDRA_INSTALL_DIR=$(pwd)/.github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC
unzip .github/ghidrathon/Ghidrathon-${{ matrix.ghidrathon-version }}/dist/*.zip -d .github/ghidra/ghidra_${{ matrix.ghidra-version }}_PUBLIC/Ghidra/Extensions
- name: Install pyyaml
run: sudo apt-get install -y libyaml-dev
- name: Install capa
run: pip install -e .[dev]
- name: Run tests
run: |
mkdir ./.github/ghidra/project
.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

20
.gitignore vendored
View File

@@ -108,9 +108,21 @@ venv.bak/
*.viv
*.idb
*.i64
.vscode
!rules/lib
# hooks/ci.sh output
isort-output.log
black-output.log
rule-linter-output.log
scripts/perf/*.txt
scripts/perf/*.svg
scripts/perf/*.zip
.direnv
.envrc
.DS_Store
*/.DS_Store
Pipfile
Pipfile.lock
/cache/
.github/binja/binaryninja
.github/binja/download_headless.py
.github/binja/BinaryNinja-headless.zip

2
.gitmodules vendored
View File

@@ -1,6 +1,8 @@
[submodule "rules"]
path = rules
url = ../capa-rules.git
branch = dynamic-syntax
[submodule "tests/data"]
path = tests/data
url = ../capa-testfiles.git
branch = dynamic-feature-extractor

129
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,129 @@
# install the pre-commit hooks:
#
# pre-commit install --hook-type pre-commit
# pre-commit installed at .git/hooks/pre-commit
#
# pre-commit install --hook-type pre-push
# pre-commit installed at .git/hooks/pre-push
#
# run all linters liks:
#
# pre-commit run --all-files
# isort....................................................................Passed
# black....................................................................Passed
# ruff.....................................................................Passed
# flake8...................................................................Passed
# mypy.....................................................................Passed
#
# run a single linter like:
#
# pre-commit run --all-files isort
# isort....................................................................Passed
repos:
- repo: local
hooks:
- id: isort
name: isort
stages: [commit, push, manual]
language: system
entry: isort
args:
- "--length-sort"
- "--profile"
- "black"
- "--line-length=120"
- "--skip-glob"
- "*_pb2.py"
- "capa/"
- "scripts/"
- "tests/"
always_run: true
pass_filenames: false
- repo: local
hooks:
- id: black
name: black
stages: [commit, push, manual]
language: system
entry: black
args:
- "--line-length=120"
- "--extend-exclude"
- ".*_pb2.py"
- "capa/"
- "scripts/"
- "tests/"
always_run: true
pass_filenames: false
- repo: local
hooks:
- id: ruff
name: ruff
stages: [commit, push, manual]
language: system
entry: ruff
args:
- "check"
- "--config"
- ".github/ruff.toml"
- "capa/"
- "scripts/"
- "tests/"
always_run: true
pass_filenames: false
- repo: local
hooks:
- id: flake8
name: flake8
stages: [push, manual]
language: system
entry: flake8
args:
- "--config"
- ".github/flake8.ini"
- "--extend-exclude"
- "capa/render/proto/capa_pb2.py"
- "capa/"
- "scripts/"
- "tests/"
always_run: true
pass_filenames: false
- repo: local
hooks:
- id: mypy
name: mypy
stages: [push, manual]
language: system
entry: mypy
args:
- "--check-untyped-defs"
- "--ignore-missing-imports"
- "--config-file=.github/mypy/mypy.ini"
- "capa/"
- "scripts/"
- "tests/"
always_run: true
pass_filenames: false
- repo: local
hooks:
- id: pytest-fast
name: pytest (fast)
stages: [manual]
language: system
entry: pytest
args:
- "tests/"
- "--ignore=tests/test_binja_features.py"
- "--ignore=tests/test_ghidra_features.py"
- "--ignore=tests/test_ida_features.py"
- "--ignore=tests/test_viv_features.py"
- "--ignore=tests/test_main.py"
- "--ignore=tests/test_scripts.py"
always_run: true
pass_filenames: false

File diff suppressed because it is too large Load Diff

View File

@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (C) 2020 FireEye, Inc.
Copyright (C) 2023 Mandiant, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

215
README.md
View File

@@ -1,14 +1,21 @@
![capa](.github/logo.png)
![capa](https://github.com/mandiant/capa/blob/master/.github/logo.png)
[![CI status](https://github.com/fireeye/capa/workflows/CI/badge.svg)](https://github.com/fireeye/capa/actions?query=workflow%3ACI+event%3Apush+branch%3Amaster)
[![Number of rules](https://img.shields.io/badge/rules-341-blue.svg)](https://github.com/fireeye/capa-rules)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/flare-capa)](https://pypi.org/project/flare-capa)
[![Last release](https://img.shields.io/github/v/release/mandiant/capa)](https://github.com/mandiant/capa/releases)
[![Number of rules](https://img.shields.io/badge/rules-859-blue.svg)](https://github.com/mandiant/capa-rules)
[![CI status](https://github.com/mandiant/capa/workflows/CI/badge.svg)](https://github.com/mandiant/capa/actions?query=workflow%3ACI+event%3Apush+branch%3Amaster)
[![Downloads](https://img.shields.io/github/downloads/mandiant/capa/total)](https://github.com/mandiant/capa/releases)
[![License](https://img.shields.io/badge/license-Apache--2.0-green.svg)](LICENSE.txt)
capa detects capabilities in executable files.
You run it against a PE file or shellcode and it tells you what it thinks the program can do.
You run it against a PE, ELF, .NET module, shellcode file, or a sandbox report and it tells you what it thinks the program can do.
For example, it might suggest that the file is a backdoor, is capable of installing services, or relies on HTTP to communicate.
Check out the overview in our first [capa blog post](https://www.fireeye.com/blog/threat-research/2020/07/capa-automatically-identify-malware-capabilities.html).
Check out:
- the overview in our first [capa blog post](https://www.mandiant.com/resources/capa-automatically-identify-malware-capabilities)
- the major version 2.0 updates described in our [second blog post](https://www.mandiant.com/resources/capa-2-better-stronger-faster)
- the major version 3.0 (ELF support) described in the [third blog post](https://www.mandiant.com/resources/elfant-in-the-room-capa-v3)
- the major version 4.0 (.NET support) described in the [fourth blog post](https://www.mandiant.com/resources/blog/capa-v4-casting-wider-net)
```
$ capa.exe suspicious.exe
@@ -60,18 +67,11 @@ $ capa.exe suspicious.exe
# download and usage
Download stable releases of the standalone capa binaries [here](https://github.com/fireeye/capa/releases). You can run the standalone binaries without installation. capa is a command line tool that should be run from the terminal.
Download stable releases of the standalone capa binaries [here](https://github.com/mandiant/capa/releases). You can run the standalone binaries without installation. capa is a command line tool that should be run from the terminal.
<!--
Alternatively, you can fetch a nightly build of a standalone binary from one of the following links. These are built using the latest development branch.
- Windows 64bit: TODO
- Linux: TODO
- OSX: TODO
-->
To use capa as a library or integrate with another tool, see [doc/installation.md](https://github.com/mandiant/capa/blob/master/doc/installation.md) for further setup instructions.
To use capa as a library or integrate with another tool, see [doc/installation.md](doc/installation.md) for further setup instructions.
For more information about how to use capa, including running it as an IDA script/plugin see [doc/usage.md](doc/usage.md).
For more information about how to use capa, see [doc/usage.md](https://github.com/mandiant/capa/blob/master/doc/usage.md).
# example
@@ -88,34 +88,133 @@ This is useful for at least two reasons:
- it shows where within the binary an experienced analyst might study with IDA Pro
```
λ capa.exe suspicious.exe -vv
$ capa.exe suspicious.exe -vv
...
execute shell command and capture output
namespace c2/shell
author matthew.williams@fireeye.com
author matthew.williams@mandiant.com
scope function
att&ck Execution::Command and Scripting Interpreter::Windows Command Shell [T1059.003]
references https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
examples Practical Malware Analysis Lab 14-02.exe_:0x4011C0
function @ 0x10003A13
function @ 0x4011C0
and:
match: create a process with modified I/O handles and window @ 0x10003A13
match: create a process with modified I/O handles and window @ 0x4011C0
and:
number: 257 = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW @ 0x4012B8
or:
api: kernel32.CreateProcess @ 0x10003D6D
number: 0x101 @ 0x10003B03
or:
number: 0x44 @ 0x10003ADC
optional:
api: kernel32.GetStartupInfo @ 0x10003AE4
match: create pipe @ 0x10003A13
number: 68 = StartupInfo.cb (size) @ 0x401282
or: = API functions that accept a pointer to a STARTUPINFO structure
api: kernel32.CreateProcess @ 0x401343
match: create pipe @ 0x4011C0
or:
api: kernel32.CreatePipe @ 0x10003ACB
api: kernel32.CreatePipe @ 0x40126F, 0x401280
optional:
match: create thread @ 0x40136A, 0x4013BA
or:
and:
os: windows
or:
api: kernel32.CreateThread @ 0x4013D7
or:
and:
os: windows
or:
api: kernel32.CreateThread @ 0x401395
or:
string: cmd.exe /c @ 0x10003AED
string: "cmd.exe" @ 0x4012FD
...
```
Additionally, capa also supports analyzing [CAPE](https://github.com/kevoreilly/CAPEv2) sandbox reports for dynamic capabilty extraction.
In order to use this, you first submit your sample to CAPE for analysis, and then run capa against the generated report (JSON).
Here's an example of running capa against a packed binary, and then running capa against the CAPE report of that binary:
```yaml
$ capa 05be49819139a3fdcdbddbdefd298398779521f3d68daa25275cc77508e42310.exe
WARNING:capa.capabilities.common:--------------------------------------------------------------------------------
WARNING:capa.capabilities.common: This sample appears to be packed.
WARNING:capa.capabilities.common:
WARNING:capa.capabilities.common: Packed samples have often been obfuscated to hide their logic.
WARNING:capa.capabilities.common: capa cannot handle obfuscation well using static analysis. This means the results may be misleading or incomplete.
WARNING:capa.capabilities.common: If possible, you should try to unpack this input file before analyzing it with capa.
WARNING:capa.capabilities.common: Alternatively, run the sample in a supported sandbox and invoke capa against the report to obtain dynamic analysis results.
WARNING:capa.capabilities.common:
WARNING:capa.capabilities.common: Identified via rule: (internal) packer file limitation
WARNING:capa.capabilities.common:
WARNING:capa.capabilities.common: Use -v or -vv if you really want to see the capabilities identified by capa.
WARNING:capa.capabilities.common:--------------------------------------------------------------------------------
$ capa 05be49819139a3fdcdbddbdefd298398779521f3d68daa25275cc77508e42310.json
┍━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┑
│ ATT&CK Tactic │ ATT&CK Technique │
┝━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
│ CREDENTIAL ACCESS │ Credentials from Password Stores T1555 │
├────────────────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ DEFENSE EVASION │ File and Directory Permissions Modification T1222 │
│ │ Modify Registry T1112 │
│ │ Obfuscated Files or Information T1027 │
│ │ Virtualization/Sandbox Evasion::User Activity Based Checks T1497.002 │
├────────────────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ DISCOVERY │ Account Discovery T1087 │
│ │ Application Window Discovery T1010 │
│ │ File and Directory Discovery T1083 │
│ │ Query Registry T1012 │
│ │ System Information Discovery T1082 │
│ │ System Location Discovery::System Language Discovery T1614.001 │
│ │ System Owner/User Discovery T1033 │
├────────────────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ EXECUTION │ System Services::Service Execution T1569.002 │
├────────────────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ PERSISTENCE │ Boot or Logon Autostart Execution::Registry Run Keys / Startup Folder T1547.001 │
│ │ Boot or Logon Autostart Execution::Winlogon Helper DLL T1547.004 │
│ │ Create or Modify System Process::Windows Service T1543.003 │
┕━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┙
┍━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┑
│ Capability │ Namespace │
┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
│ check for unmoving mouse cursor (3 matches) │ anti-analysis/anti-vm/vm-detection │
│ gather bitkinex information │ collection/file-managers │
│ gather classicftp information │ collection/file-managers │
│ gather filezilla information │ collection/file-managers │
│ gather total-commander information │ collection/file-managers │
│ gather ultrafxp information │ collection/file-managers │
│ resolve DNS (23 matches) │ communication/dns │
│ initialize Winsock library (7 matches) │ communication/socket │
│ act as TCP client (3 matches) │ communication/tcp/client │
│ create new key via CryptAcquireContext │ data-manipulation/encryption │
│ encrypt or decrypt via WinCrypt │ data-manipulation/encryption │
│ hash data via WinCrypt │ data-manipulation/hashing │
│ initialize hashing via WinCrypt │ data-manipulation/hashing │
│ hash data with MD5 │ data-manipulation/hashing/md5 │
│ generate random numbers via WinAPI │ data-manipulation/prng │
│ extract resource via kernel32 functions (2 matches) │ executable/resource │
│ interact with driver via control codes (2 matches) │ host-interaction/driver │
│ get Program Files directory (18 matches) │ host-interaction/file-system │
│ get common file path (575 matches) │ host-interaction/file-system │
│ create directory (2 matches) │ host-interaction/file-system/create │
│ delete file │ host-interaction/file-system/delete │
│ get file attributes (122 matches) │ host-interaction/file-system/meta │
│ set file attributes (8 matches) │ host-interaction/file-system/meta │
│ move file │ host-interaction/file-system/move │
│ find taskbar (3 matches) │ host-interaction/gui/taskbar/find │
│ get keyboard layout (12 matches) │ host-interaction/hardware/keyboard │
│ get disk size │ host-interaction/hardware/storage │
│ get hostname (4 matches) │ host-interaction/os/hostname │
│ allocate or change RWX memory (3 matches) │ host-interaction/process/inject │
│ query or enumerate registry key (3 matches) │ host-interaction/registry │
│ query or enumerate registry value (8 matches) │ host-interaction/registry │
│ delete registry key │ host-interaction/registry/delete │
│ start service │ host-interaction/service/start │
│ get session user name │ host-interaction/session │
│ persist via Run registry key │ persistence/registry/run │
│ persist via Winlogon Helper DLL registry key │ persistence/registry/winlogon-helper │
│ persist via Windows service (2 matches) │ persistence/service │
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┙
```
capa uses a collection of rules to identify capabilities within a program.
These rules are easy to write, even for those new to reverse engineering.
By authoring rules, you can extend the capabilities that capa recognizes.
@@ -126,40 +225,52 @@ Here's an example rule used by capa:
```yaml
rule:
meta:
name: hash data with CRC32
namespace: data-manipulation/checksum/crc32
author: moritz.raabe@fireeye.com
scope: function
name: create TCP socket
namespace: communication/socket/tcp
authors:
- william.ballenthin@mandiant.com
- joakim@intezer.com
- anushka.virgaonkar@mandiant.com
scopes:
static: basic block
dynamic: call
mbc:
- Communication::Socket Communication::Create TCP Socket [C0001.011]
examples:
- 2D3EDC218A90F03089CC01715A9F047F:0x403CBD
- 7D28CB106CB54876B2A5C111724A07CD:0x402350 # RtlComputeCrc32
- Practical Malware Analysis Lab 01-01.dll_:0x10001010
features:
- or:
- and:
- mnemonic: shr
- number: 0xEDB88320
- number: 8
- characteristic: nzxor
- api: RtlComputeCrc32
- number: 6 = IPPROTO_TCP
- number: 1 = SOCK_STREAM
- number: 2 = AF_INET
- or:
- api: ws2_32.socket
- api: ws2_32.WSASocket
- api: socket
- property/read: System.Net.Sockets.TcpClient::Client
```
The [github.com/fireeye/capa-rules](https://github.com/fireeye/capa-rules) repository contains hundreds of standard library rules that are distributed with capa.
The [github.com/mandiant/capa-rules](https://github.com/mandiant/capa-rules) repository contains hundreds of standard library rules that are distributed with capa.
Please learn to write rules and contribute new entries as you find interesting techniques in malware.
If you use IDA Pro, then you use can use the [IDA Pro plugin for capa](./capa/ida/ida_capa_explorer.py).
This script adds new user interface elements to IDA, including an interactive tree view of rule matches and their locations within the current database.
As you select the checkboxes, the plugin will highlight the addresses associated with the features.
We use this plugin all the time to quickly jump to interesting parts of a program.
If you use IDA Pro, then you can use the [capa explorer](https://github.com/mandiant/capa/tree/master/capa/ida/plugin) plugin.
capa explorer helps you identify interesting areas of a program and build new capa rules using features extracted directly from your IDA Pro database.
![capa + IDA Pro integration](.github/capa-ida.jpg)
![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
- [doc/installation](doc/installation.md)
- [doc/usage](doc/usage.md)
- [doc/limitations](doc/limitations.md)
- [Contributing Guide](.github/CONTRIBUTING.md)
- [Installation](https://github.com/mandiant/capa/blob/master/doc/installation.md)
- [Usage](https://github.com/mandiant/capa/blob/master/doc/usage.md)
- [Limitations](https://github.com/mandiant/capa/blob/master/doc/limitations.md)
- [Contributing Guide](https://github.com/mandiant/capa/blob/master/.github/CONTRIBUTING.md)
## capa rules
- [capa-rules repository](https://github.com/fireeye/capa-rules)
- [capa-rules rule format](https://github.com/fireeye/capa-rules/blob/master/doc/format.md)
- [capa-rules repository](https://github.com/mandiant/capa-rules)
- [capa-rules rule format](https://github.com/mandiant/capa-rules/blob/master/doc/format.md)
## capa testfiles
The [capa-testfiles repository](https://github.com/mandiant/capa-testfiles) contains the data we use to test capa's code and rules

BIN
assets/classes.json.gz Normal file

Binary file not shown.

BIN
assets/interfaces.json.gz Normal file

Binary file not shown.

View File

@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
# 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 itertools
import collections
from typing import Any, Tuple
from capa.rules import Scope, RuleSet
from capa.engine import FeatureSet, MatchResults
from capa.features.address import NO_ADDRESS
from capa.features.extractors.base_extractor import FeatureExtractor, StaticFeatureExtractor, DynamicFeatureExtractor
logger = logging.getLogger(__name__)
def find_file_capabilities(ruleset: RuleSet, extractor: FeatureExtractor, function_features: FeatureSet):
file_features: FeatureSet = collections.defaultdict(set)
for feature, va in itertools.chain(extractor.extract_file_features(), extractor.extract_global_features()):
# not all file features may have virtual addresses.
# if not, then at least ensure the feature shows up in the index.
# the set of addresses will still be empty.
if va:
file_features[feature].add(va)
else:
if feature not in file_features:
file_features[feature] = set()
logger.debug("analyzed file and extracted %d features", len(file_features))
file_features.update(function_features)
_, matches = ruleset.match(Scope.FILE, file_features, NO_ADDRESS)
return matches, len(file_features)
def has_file_limitation(rules: RuleSet, capabilities: MatchResults, is_standalone=True) -> bool:
file_limitation_rules = list(filter(lambda r: r.is_file_limitation_rule(), rules.rules.values()))
for file_limitation_rule in file_limitation_rules:
if file_limitation_rule.name not in capabilities:
continue
logger.warning("-" * 80)
for line in file_limitation_rule.meta.get("description", "").split("\n"):
logger.warning(" %s", line)
logger.warning(" Identified via rule: %s", file_limitation_rule.name)
if is_standalone:
logger.warning(" ")
logger.warning(" Use -v or -vv if you really want to see the capabilities identified by capa.")
logger.warning("-" * 80)
# bail on first file limitation
return True
return False
def find_capabilities(
ruleset: RuleSet, extractor: FeatureExtractor, disable_progress=None, **kwargs
) -> Tuple[MatchResults, Any]:
from capa.capabilities.static import find_static_capabilities
from capa.capabilities.dynamic import find_dynamic_capabilities
if isinstance(extractor, StaticFeatureExtractor):
# for the time being, extractors are either static or dynamic.
# Remove this assertion once that has changed
assert not isinstance(extractor, DynamicFeatureExtractor)
return find_static_capabilities(ruleset, extractor, disable_progress=disable_progress, **kwargs)
if isinstance(extractor, DynamicFeatureExtractor):
return find_dynamic_capabilities(ruleset, extractor, disable_progress=disable_progress, **kwargs)
raise ValueError(f"unexpected extractor type: {extractor.__class__.__name__}")

View File

@@ -0,0 +1,198 @@
# -*- coding: utf-8 -*-
# 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 itertools
import collections
from typing import Any, Tuple
import tqdm
import capa.perf
import capa.features.freeze as frz
import capa.render.result_document as rdoc
from capa.rules import Scope, RuleSet
from capa.engine import FeatureSet, MatchResults
from capa.helpers import redirecting_print_to_tqdm
from capa.capabilities.common import find_file_capabilities
from capa.features.extractors.base_extractor import CallHandle, ThreadHandle, ProcessHandle, DynamicFeatureExtractor
logger = logging.getLogger(__name__)
def find_call_capabilities(
ruleset: RuleSet, extractor: DynamicFeatureExtractor, ph: ProcessHandle, th: ThreadHandle, ch: CallHandle
) -> Tuple[FeatureSet, MatchResults]:
"""
find matches for the given rules for the given call.
returns: tuple containing (features for call, match results for call)
"""
# all features found for the call.
features: FeatureSet = collections.defaultdict(set)
for feature, addr in itertools.chain(
extractor.extract_call_features(ph, th, ch), extractor.extract_global_features()
):
features[feature].add(addr)
# matches found at this thread.
_, matches = ruleset.match(Scope.CALL, features, ch.address)
for rule_name, res in matches.items():
rule = ruleset[rule_name]
for addr, _ in res:
capa.engine.index_rule_matches(features, rule, [addr])
return features, matches
def find_thread_capabilities(
ruleset: RuleSet, extractor: DynamicFeatureExtractor, ph: ProcessHandle, th: ThreadHandle
) -> Tuple[FeatureSet, MatchResults, MatchResults]:
"""
find matches for the given rules within the given thread.
returns: tuple containing (features for thread, match results for thread, match results for calls)
"""
# all features found within this thread,
# includes features found within calls.
features: FeatureSet = collections.defaultdict(set)
# matches found at the call scope.
# might be found at different calls, thats ok.
call_matches: MatchResults = collections.defaultdict(list)
for ch in extractor.get_calls(ph, th):
ifeatures, imatches = find_call_capabilities(ruleset, extractor, ph, th, ch)
for feature, vas in ifeatures.items():
features[feature].update(vas)
for rule_name, res in imatches.items():
call_matches[rule_name].extend(res)
for feature, va in itertools.chain(extractor.extract_thread_features(ph, th), extractor.extract_global_features()):
features[feature].add(va)
# matches found within this thread.
_, matches = ruleset.match(Scope.THREAD, features, th.address)
for rule_name, res in matches.items():
rule = ruleset[rule_name]
for va, _ in res:
capa.engine.index_rule_matches(features, rule, [va])
return features, matches, call_matches
def find_process_capabilities(
ruleset: RuleSet, extractor: DynamicFeatureExtractor, ph: ProcessHandle
) -> Tuple[MatchResults, MatchResults, MatchResults, int]:
"""
find matches for the given rules within the given process.
returns: tuple containing (match results for process, match results for threads, match results for calls, number of features)
"""
# all features found within this process,
# includes features found within threads (and calls).
process_features: FeatureSet = collections.defaultdict(set)
# matches found at the basic threads.
# might be found at different threads, thats ok.
thread_matches: MatchResults = collections.defaultdict(list)
# matches found at the call scope.
# might be found at different calls, thats ok.
call_matches: MatchResults = collections.defaultdict(list)
for th in extractor.get_threads(ph):
features, tmatches, cmatches = find_thread_capabilities(ruleset, extractor, ph, th)
for feature, vas in features.items():
process_features[feature].update(vas)
for rule_name, res in tmatches.items():
thread_matches[rule_name].extend(res)
for rule_name, res in cmatches.items():
call_matches[rule_name].extend(res)
for feature, va in itertools.chain(extractor.extract_process_features(ph), extractor.extract_global_features()):
process_features[feature].add(va)
_, process_matches = ruleset.match(Scope.PROCESS, process_features, ph.address)
return process_matches, thread_matches, call_matches, len(process_features)
def find_dynamic_capabilities(
ruleset: RuleSet, extractor: DynamicFeatureExtractor, disable_progress=None
) -> Tuple[MatchResults, Any]:
all_process_matches: MatchResults = collections.defaultdict(list)
all_thread_matches: MatchResults = collections.defaultdict(list)
all_call_matches: MatchResults = collections.defaultdict(list)
feature_counts = rdoc.DynamicFeatureCounts(file=0, processes=())
assert isinstance(extractor, DynamicFeatureExtractor)
with redirecting_print_to_tqdm(disable_progress):
with tqdm.contrib.logging.logging_redirect_tqdm():
pbar = tqdm.tqdm
if disable_progress:
# do not use tqdm to avoid unnecessary side effects when caller intends
# to disable progress completely
def pbar(s, *args, **kwargs):
return s
processes = list(extractor.get_processes())
pb = pbar(processes, desc="matching", unit=" processes", leave=False)
for p in pb:
process_matches, thread_matches, call_matches, feature_count = find_process_capabilities(
ruleset, extractor, p
)
feature_counts.processes += (
rdoc.ProcessFeatureCount(address=frz.Address.from_capa(p.address), count=feature_count),
)
logger.debug("analyzed %s and extracted %d features", p.address, feature_count)
for rule_name, res in process_matches.items():
all_process_matches[rule_name].extend(res)
for rule_name, res in thread_matches.items():
all_thread_matches[rule_name].extend(res)
for rule_name, res in call_matches.items():
all_call_matches[rule_name].extend(res)
# collection of features that captures the rule matches within process and thread scopes.
# mapping from feature (matched rule) to set of addresses at which it matched.
process_and_lower_features: FeatureSet = collections.defaultdict(set)
for rule_name, results in itertools.chain(
all_process_matches.items(), all_thread_matches.items(), all_call_matches.items()
):
locations = {p[0] for p in results}
rule = ruleset[rule_name]
capa.engine.index_rule_matches(process_and_lower_features, rule, locations)
all_file_matches, feature_count = find_file_capabilities(ruleset, extractor, process_and_lower_features)
feature_counts.file = feature_count
matches = dict(
itertools.chain(
# each rule exists in exactly one scope,
# so there won't be any overlap among these following MatchResults,
# and we can merge the dictionaries naively.
all_thread_matches.items(),
all_process_matches.items(),
all_call_matches.items(),
all_file_matches.items(),
)
)
meta = {
"feature_counts": feature_counts,
}
return matches, meta

233
capa/capabilities/static.py Normal file
View File

@@ -0,0 +1,233 @@
# -*- coding: utf-8 -*-
# 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 time
import logging
import itertools
import collections
from typing import Any, Tuple
import tqdm.contrib.logging
import capa.perf
import capa.features.freeze as frz
import capa.render.result_document as rdoc
from capa.rules import Scope, RuleSet
from capa.engine import FeatureSet, MatchResults
from capa.helpers import redirecting_print_to_tqdm
from capa.capabilities.common import find_file_capabilities
from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle, StaticFeatureExtractor
logger = logging.getLogger(__name__)
def find_instruction_capabilities(
ruleset: RuleSet, extractor: StaticFeatureExtractor, f: FunctionHandle, bb: BBHandle, insn: InsnHandle
) -> Tuple[FeatureSet, MatchResults]:
"""
find matches for the given rules for the given instruction.
returns: tuple containing (features for instruction, match results for instruction)
"""
# all features found for the instruction.
features: FeatureSet = collections.defaultdict(set)
for feature, addr in itertools.chain(
extractor.extract_insn_features(f, bb, insn), extractor.extract_global_features()
):
features[feature].add(addr)
# matches found at this instruction.
_, matches = ruleset.match(Scope.INSTRUCTION, features, insn.address)
for rule_name, res in matches.items():
rule = ruleset[rule_name]
for addr, _ in res:
capa.engine.index_rule_matches(features, rule, [addr])
return features, matches
def find_basic_block_capabilities(
ruleset: RuleSet, extractor: StaticFeatureExtractor, f: FunctionHandle, bb: BBHandle
) -> Tuple[FeatureSet, MatchResults, MatchResults]:
"""
find matches for the given rules within the given basic block.
returns: tuple containing (features for basic block, match results for basic block, match results for instructions)
"""
# all features found within this basic block,
# includes features found within instructions.
features: FeatureSet = collections.defaultdict(set)
# matches found at the instruction scope.
# might be found at different instructions, thats ok.
insn_matches: MatchResults = collections.defaultdict(list)
for insn in extractor.get_instructions(f, bb):
ifeatures, imatches = find_instruction_capabilities(ruleset, extractor, f, bb, insn)
for feature, vas in ifeatures.items():
features[feature].update(vas)
for rule_name, res in imatches.items():
insn_matches[rule_name].extend(res)
for feature, va in itertools.chain(
extractor.extract_basic_block_features(f, bb), extractor.extract_global_features()
):
features[feature].add(va)
# matches found within this basic block.
_, matches = ruleset.match(Scope.BASIC_BLOCK, features, bb.address)
for rule_name, res in matches.items():
rule = ruleset[rule_name]
for va, _ in res:
capa.engine.index_rule_matches(features, rule, [va])
return features, matches, insn_matches
def find_code_capabilities(
ruleset: RuleSet, extractor: StaticFeatureExtractor, fh: FunctionHandle
) -> Tuple[MatchResults, MatchResults, MatchResults, int]:
"""
find matches for the given rules within the given function.
returns: tuple containing (match results for function, match results for basic blocks, match results for instructions, number of features)
"""
# all features found within this function,
# includes features found within basic blocks (and instructions).
function_features: FeatureSet = collections.defaultdict(set)
# matches found at the basic block scope.
# might be found at different basic blocks, thats ok.
bb_matches: MatchResults = collections.defaultdict(list)
# matches found at the instruction scope.
# might be found at different instructions, thats ok.
insn_matches: MatchResults = collections.defaultdict(list)
for bb in extractor.get_basic_blocks(fh):
features, bmatches, imatches = find_basic_block_capabilities(ruleset, extractor, fh, bb)
for feature, vas in features.items():
function_features[feature].update(vas)
for rule_name, res in bmatches.items():
bb_matches[rule_name].extend(res)
for rule_name, res in imatches.items():
insn_matches[rule_name].extend(res)
for feature, va in itertools.chain(extractor.extract_function_features(fh), extractor.extract_global_features()):
function_features[feature].add(va)
_, function_matches = ruleset.match(Scope.FUNCTION, function_features, fh.address)
return function_matches, bb_matches, insn_matches, len(function_features)
def find_static_capabilities(
ruleset: RuleSet, extractor: StaticFeatureExtractor, disable_progress=None
) -> Tuple[MatchResults, Any]:
all_function_matches: MatchResults = collections.defaultdict(list)
all_bb_matches: MatchResults = collections.defaultdict(list)
all_insn_matches: MatchResults = collections.defaultdict(list)
feature_counts = rdoc.StaticFeatureCounts(file=0, functions=())
library_functions: Tuple[rdoc.LibraryFunction, ...] = ()
assert isinstance(extractor, StaticFeatureExtractor)
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
def pbar(s, *args, **kwargs):
return s
functions = list(extractor.get_functions())
n_funcs = len(functions)
pb = pbar(functions, desc="matching", unit=" functions", postfix="skipped 0 library functions", leave=False)
for f in pb:
t0 = time.time()
if extractor.is_library_function(f.address):
function_name = extractor.get_function_name(f.address)
logger.debug("skipping library function 0x%x (%s)", f.address, function_name)
library_functions += (
rdoc.LibraryFunction(address=frz.Address.from_capa(f.address), name=function_name),
)
n_libs = len(library_functions)
percentage = round(100 * (n_libs / n_funcs))
if isinstance(pb, tqdm.tqdm):
pb.set_postfix_str(f"skipped {n_libs} library functions ({percentage}%)")
continue
function_matches, bb_matches, insn_matches, feature_count = find_code_capabilities(
ruleset, extractor, f
)
feature_counts.functions += (
rdoc.FunctionFeatureCount(address=frz.Address.from_capa(f.address), count=feature_count),
)
t1 = time.time()
match_count = sum(len(res) for res in function_matches.values())
match_count += sum(len(res) for res in bb_matches.values())
match_count += sum(len(res) for res in insn_matches.values())
logger.debug(
"analyzed function 0x%x and extracted %d features, %d matches in %0.02fs",
f.address,
feature_count,
match_count,
t1 - t0,
)
for rule_name, res in function_matches.items():
all_function_matches[rule_name].extend(res)
for rule_name, res in bb_matches.items():
all_bb_matches[rule_name].extend(res)
for rule_name, res in insn_matches.items():
all_insn_matches[rule_name].extend(res)
# collection of features that captures the rule matches within function, BB, and instruction scopes.
# mapping from feature (matched rule) to set of addresses at which it matched.
function_and_lower_features: FeatureSet = collections.defaultdict(set)
for rule_name, results in itertools.chain(
all_function_matches.items(), all_bb_matches.items(), all_insn_matches.items()
):
locations = {p[0] for p in results}
rule = ruleset[rule_name]
capa.engine.index_rule_matches(function_and_lower_features, rule, locations)
all_file_matches, feature_count = find_file_capabilities(ruleset, extractor, function_and_lower_features)
feature_counts.file = feature_count
matches = dict(
itertools.chain(
# each rule exists in exactly one scope,
# so there won't be any overlap among these following MatchResults,
# and we can merge the dictionaries naively.
all_insn_matches.items(),
all_bb_matches.items(),
all_function_matches.items(),
all_file_matches.items(),
)
)
meta = {
"feature_counts": feature_counts,
"library_functions": library_functions,
}
return matches, meta

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2020 FireEye, 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
@@ -6,14 +6,31 @@
# 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 copy
import collections
from typing import TYPE_CHECKING, Set, Dict, List, Tuple, Union, Mapping, Iterable, Iterator
import capa.features
import capa.perf
import capa.features.common
from capa.features.common import Result, Feature
from capa.features.address import Address
if TYPE_CHECKING:
# circular import, otherwise
import capa.rules
class Statement(object):
# a collection of features and the locations at which they are found.
#
# used throughout matching as the context in which features are searched:
# to check if a feature exists, do: `Number(0x10) in features`.
# to collect the locations of a feature, do: `features[Number(0x10)]`
#
# aliased here so that the type can be documented and xref'd.
FeatureSet = Dict[Feature, Set[Address]]
class Statement:
"""
superclass for structural nodes, such as and/or/not.
this exists to provide a default impl for `__str__` and `__repr__`,
@@ -21,157 +38,194 @@ class Statement(object):
"""
def __init__(self, description=None):
super(Statement, self).__init__()
super().__init__()
self.name = self.__class__.__name__
self.description = description
def __str__(self):
name = self.name.lower()
children = ",".join(map(str, self.get_children()))
if self.description:
return "%s(%s = %s)" % (self.name.lower(), ",".join(map(str, self.get_children())), self.description)
return f"{name}({children} = {self.description})"
else:
return "%s(%s)" % (self.name.lower(), ",".join(map(str, self.get_children())))
return f"{name}({children})"
def __repr__(self):
return str(self)
def evaluate(self, ctx):
def evaluate(self, features: FeatureSet, short_circuit=True) -> Result:
"""
classes that inherit `Statement` must implement `evaluate`
args:
ctx (defaultdict[Feature, set[VA]])
returns:
Result
short_circuit (bool): if true, then statements like and/or/some may short circuit.
"""
raise NotImplementedError()
def get_children(self):
def get_children(self) -> Iterator[Union["Statement", Feature]]:
if hasattr(self, "child"):
yield self.child
# this really confuses mypy because the property may not exist
# since its defined in the subclasses.
child = self.child # type: ignore
assert isinstance(child, (Statement, Feature))
yield child
if hasattr(self, "children"):
for child in self.children:
assert isinstance(child, (Statement, Feature))
yield child
def replace_child(self, existing, new):
if hasattr(self, "child"):
if self.child is existing:
# this really confuses mypy because the property may not exist
# since its defined in the subclasses.
if self.child is existing: # type: ignore
self.child = new
if hasattr(self, "children"):
for i, child in enumerate(self.children):
children = self.children
for i, child in enumerate(children):
if child is existing:
self.children[i] = new
class Result(object):
"""
represents the results of an evaluation of statements against features.
instances of this class should behave like a bool,
e.g. `assert Result(True, ...) == True`
instances track additional metadata about evaluation results.
they contain references to the statement node (e.g. an And statement),
as well as the children Result instances.
we need this so that we can render the tree of expressions and their results.
"""
def __init__(self, success, statement, children, locations=None):
"""
args:
success (bool)
statement (capa.engine.Statement or capa.features.Feature)
children (list[Result])
locations (iterable[VA])
"""
super(Result, self).__init__()
self.success = success
self.statement = statement
self.children = children
self.locations = locations if locations is not None else ()
def __eq__(self, other):
if isinstance(other, bool):
return self.success == other
return False
def __bool__(self):
return self.success
def __nonzero__(self):
return self.success
children[i] = new
class And(Statement):
"""match if all of the children evaluate to True."""
"""
match if all of the children evaluate to True.
the order of evaluation is dictated by the property
`And.children` (type: List[Statement|Feature]).
a query optimizer may safely manipulate the order of these children.
"""
def __init__(self, children, description=None):
super(And, self).__init__(description=description)
super().__init__(description=description)
self.children = children
def evaluate(self, ctx):
results = [child.evaluate(ctx) for child in self.children]
success = all(results)
return Result(success, self, results)
def evaluate(self, ctx, short_circuit=True):
capa.perf.counters["evaluate.feature"] += 1
capa.perf.counters["evaluate.feature.and"] += 1
if short_circuit:
results = []
for child in self.children:
result = child.evaluate(ctx, short_circuit=short_circuit)
results.append(result)
if not result:
# short circuit
return Result(False, self, results)
return Result(True, self, results)
else:
results = [child.evaluate(ctx, short_circuit=short_circuit) for child in self.children]
success = all(results)
return Result(success, self, results)
class Or(Statement):
"""match if any of the children evaluate to True."""
"""
match if any of the children evaluate to True.
the order of evaluation is dictated by the property
`Or.children` (type: List[Statement|Feature]).
a query optimizer may safely manipulate the order of these children.
"""
def __init__(self, children, description=None):
super(Or, self).__init__(description=description)
super().__init__(description=description)
self.children = children
def evaluate(self, ctx):
results = [child.evaluate(ctx) for child in self.children]
success = any(results)
return Result(success, self, results)
def evaluate(self, ctx, short_circuit=True):
capa.perf.counters["evaluate.feature"] += 1
capa.perf.counters["evaluate.feature.or"] += 1
if short_circuit:
results = []
for child in self.children:
result = child.evaluate(ctx, short_circuit=short_circuit)
results.append(result)
if result:
# short circuit as soon as we hit one match
return Result(True, self, results)
return Result(False, self, results)
else:
results = [child.evaluate(ctx, short_circuit=short_circuit) for child in self.children]
success = any(results)
return Result(success, self, results)
class Not(Statement):
"""match only if the child evaluates to False."""
def __init__(self, child, description=None):
super(Not, self).__init__(description=description)
super().__init__(description=description)
self.child = child
def evaluate(self, ctx):
results = [self.child.evaluate(ctx)]
def evaluate(self, ctx, short_circuit=True):
capa.perf.counters["evaluate.feature"] += 1
capa.perf.counters["evaluate.feature.not"] += 1
results = [self.child.evaluate(ctx, short_circuit=short_circuit)]
success = not results[0]
return Result(success, self, results)
class Some(Statement):
"""match if at least N of the children evaluate to True."""
"""
match if at least N of the children evaluate to True.
the order of evaluation is dictated by the property
`Some.children` (type: List[Statement|Feature]).
a query optimizer may safely manipulate the order of these children.
"""
def __init__(self, count, children, description=None):
super(Some, self).__init__(description=description)
super().__init__(description=description)
self.count = count
self.children = children
def evaluate(self, ctx):
results = [child.evaluate(ctx) for child in self.children]
# note that here we cast the child result as a bool
# because we've overridden `__bool__` above.
#
# we can't use `if child is True` because the instance is not True.
success = sum([1 for child in results if bool(child) is True]) >= self.count
return Result(success, self, results)
def evaluate(self, ctx, short_circuit=True):
capa.perf.counters["evaluate.feature"] += 1
capa.perf.counters["evaluate.feature.some"] += 1
if short_circuit:
results = []
satisfied_children_count = 0
for child in self.children:
result = child.evaluate(ctx, short_circuit=short_circuit)
results.append(result)
if result:
satisfied_children_count += 1
if satisfied_children_count >= self.count:
# short circuit as soon as we hit the threshold
return Result(True, self, results)
return Result(False, self, results)
else:
results = [child.evaluate(ctx, short_circuit=short_circuit) for child in self.children]
# note that here we cast the child result as a bool
# because we've overridden `__bool__` above.
#
# we can't use `if child is True` because the instance is not True.
success = sum([1 for child in results if bool(child) is True]) >= self.count
return Result(success, self, results)
class Range(Statement):
"""match if the child is contained in the ctx set with a count in the given range."""
def __init__(self, child, min=None, max=None, description=None):
super(Range, self).__init__(description=description)
super().__init__(description=description)
self.child = child
self.min = min if min is not None else 0
self.max = max if max is not None else (1 << 64 - 1)
def evaluate(self, ctx):
def evaluate(self, ctx, **kwargs):
capa.perf.counters["evaluate.feature"] += 1
capa.perf.counters["evaluate.feature.range"] += 1
count = len(ctx.get(self.child, []))
if self.min == 0 and count == 0:
return Result(True, self, [])
@@ -180,9 +234,9 @@ class Range(Statement):
def __str__(self):
if self.max == (1 << 64 - 1):
return "range(%s, min=%d, max=infinity)" % (str(self.child), self.min)
return f"range({str(self.child)}, min={self.min}, max=infinity)"
else:
return "range(%s, min=%d, max=%d)" % (str(self.child), self.min, self.max)
return f"range({str(self.child)}, min={self.min}, max={self.max})"
class Subscope(Statement):
@@ -191,59 +245,66 @@ class Subscope(Statement):
the engine should preprocess rules to extract subscope statements into their own rules.
"""
def __init__(self, scope, child):
super(Subscope, self).__init__()
def __init__(self, scope, child, description=None):
super().__init__(description=description)
self.scope = scope
self.child = child
def evaluate(self, ctx):
def evaluate(self, ctx, **kwargs):
raise ValueError("cannot evaluate a subscope directly!")
def topologically_order_rules(rules):
# mapping from rule name to list of: (location of match, result object)
#
# used throughout matching and rendering to collection the results
# of statement evaluation and their locations.
#
# to check if a rule matched, do: `"TCP client" in matches`.
# to find where a rule matched, do: `map(first, matches["TCP client"])`
# to see how a rule matched, do:
#
# for address, match_details in matches["TCP client"]:
# inspect(match_details)
#
# aliased here so that the type can be documented and xref'd.
MatchResults = Mapping[str, List[Tuple[Address, Result]]]
def index_rule_matches(features: FeatureSet, rule: "capa.rules.Rule", locations: Iterable[Address]):
"""
order the given rules such that dependencies show up before dependents.
this means that as we match rules, we can add features for the matches, and these
will be matched by subsequent rules if they follow this order.
record into the given featureset that the given rule matched at the given locations.
assumes that the rule dependency graph is a DAG.
naively, this is just adding a MatchedRule feature;
however, we also want to record matches for the rule's namespaces.
updates `features` in-place. doesn't modify the remaining arguments.
"""
# we evaluate `rules` multiple times, so if its a generator, realize it into a list.
rules = list(rules)
namespaces = capa.rules.index_rules_by_namespace(rules)
rules = {rule.name: rule for rule in rules}
seen = set([])
ret = []
def rec(rule):
if rule.name in seen:
return
for dep in rule.get_dependencies(namespaces):
rec(rules[dep])
ret.append(rule)
seen.add(rule.name)
for rule in rules.values():
rec(rule)
return ret
features[capa.features.common.MatchedRule(rule.name)].update(locations)
namespace = rule.meta.get("namespace")
if namespace:
while namespace:
features[capa.features.common.MatchedRule(namespace)].update(locations)
namespace, _, _ = namespace.rpartition("/")
def match(rules, features, va):
def match(rules: List["capa.rules.Rule"], features: FeatureSet, addr: Address) -> Tuple[FeatureSet, MatchResults]:
"""
Args:
rules (List[capa.rules.Rule]): these must already be ordered topologically by dependency.
features (Mapping[capa.features.Feature, int]):
va (int): location of the features
match the given rules against the given features,
returning an updated set of features and the matches.
Returns:
Tuple[List[capa.features.Feature], Dict[str, Tuple[int, capa.engine.Result]]]: two-tuple with entries:
- list of features used for matching (which may be greater than argument, due to rule match features), and
- mapping from rule name to (location of match, result object)
the updated features are just like the input,
but extended to include the match features (e.g. names of rules that matched).
the given feature set is not modified; an updated copy is returned.
the given list of rules must be ordered topologically by dependency,
or else `match` statements will not be handled correctly.
this routine should be fairly optimized, but is not guaranteed to be the fastest matcher possible.
it has a particularly convenient signature: (rules, features) -> matches
other strategies can be imagined that match differently; implement these elsewhere.
specifically, this routine does "top down" matching of the given rules against the feature set.
"""
results = collections.defaultdict(list)
results: MatchResults = collections.defaultdict(list)
# copy features so that we can modify it
# without affecting the caller (keep this function pure)
@@ -252,15 +313,22 @@ def match(rules, features, va):
features = collections.defaultdict(set, copy.copy(features))
for rule in rules:
res = rule.evaluate(features)
res = rule.evaluate(features, short_circuit=True)
if res:
results[rule.name].append((va, res))
features[capa.features.MatchedRule(rule.name)].add(va)
# we first matched the rule with short circuiting enabled.
# this is much faster than without short circuiting.
# however, we want to collect all results thoroughly,
# so once we've found a match quickly,
# go back and capture results without short circuiting.
res = rule.evaluate(features, short_circuit=False)
namespace = rule.meta.get("namespace")
if namespace:
while namespace:
features[capa.features.MatchedRule(namespace)].add(va)
namespace, _, _ = namespace.rpartition("/")
# sanity check
assert bool(res) is True
results[rule.name].append((addr, res))
# we need to update the current `features`
# because subsequent iterations of this loop may use newly added features,
# such as rule or namespace matches.
index_rule_matches(features, rule, [addr])
return (features, results)

25
capa/exceptions.py Normal file
View File

@@ -0,0 +1,25 @@
# 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.
class UnsupportedRuntimeError(RuntimeError):
pass
class UnsupportedFormatError(ValueError):
pass
class UnsupportedArchError(ValueError):
pass
class UnsupportedOSError(ValueError):
pass
class EmptyReportError(ValueError):
pass

View File

@@ -1,192 +0,0 @@
# Copyright (C) 2020 FireEye, 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 re
import sys
import codecs
import logging
import capa.engine
logger = logging.getLogger(__name__)
MAX_BYTES_FEATURE_SIZE = 0x100
# identifiers for supported architectures names that tweak a feature
# for example, offset/x32
ARCH_X32 = "x32"
ARCH_X64 = "x64"
VALID_ARCH = (ARCH_X32, ARCH_X64)
def bytes_to_str(b):
if sys.version_info[0] >= 3:
return str(codecs.encode(b, "hex").decode("utf-8"))
else:
return codecs.encode(b, "hex")
def hex_string(h):
""" render hex string e.g. "0a40b1" as "0A 40 B1" """
return " ".join(h[i : i + 2] for i in range(0, len(h), 2)).upper()
class Feature(object):
def __init__(self, value, arch=None, description=None):
"""
Args:
value (any): the value of the feature, such as the number or string.
arch (str): one of the VALID_ARCH values, or None.
When None, then the feature applies to any architecture.
Modifies the feature name from `feature` to `feature/arch`, like `offset/x32`.
description (str): a human-readable description that explains the feature value.
"""
super(Feature, self).__init__()
if arch is not None:
if arch not in VALID_ARCH:
raise ValueError("arch '%s' must be one of %s" % (arch, VALID_ARCH))
self.name = self.__class__.__name__.lower() + "/" + arch
else:
self.name = self.__class__.__name__.lower()
self.value = value
self.arch = arch
self.description = description
def __hash__(self):
return hash((self.name, self.value, self.arch))
def __eq__(self, other):
return self.name == other.name and self.value == other.value and self.arch == other.arch
def get_value_str(self):
"""
render the value of this feature, for use by `__str__` and friends.
subclasses should override to customize the rendering.
Returns: any
"""
return self.value
def __str__(self):
if self.value:
if self.description:
return "%s(%s = %s)" % (self.name, self.get_value_str(), self.description)
else:
return "%s(%s)" % (self.name, self.get_value_str())
else:
return "%s" % self.name
def __repr__(self):
return str(self)
def evaluate(self, ctx):
return capa.engine.Result(self in ctx, self, [], locations=ctx.get(self, []))
def freeze_serialize(self):
if self.arch is not None:
return (self.__class__.__name__, [self.value, {"arch": self.arch}])
else:
return (self.__class__.__name__, [self.value])
@classmethod
def freeze_deserialize(cls, args):
# as you can see below in code,
# if the last argument is a dictionary,
# consider it to be kwargs passed to the feature constructor.
if len(args) == 1:
return cls(*args)
elif isinstance(args[-1], dict):
kwargs = args[-1]
args = args[:-1]
return cls(*args, **kwargs)
class MatchedRule(Feature):
def __init__(self, value, description=None):
super(MatchedRule, self).__init__(value, description=description)
self.name = "match"
class Characteristic(Feature):
def __init__(self, value, description=None):
super(Characteristic, self).__init__(value, description=description)
class String(Feature):
def __init__(self, value, description=None):
super(String, self).__init__(value, description=description)
class Regex(String):
def __init__(self, value, description=None):
super(Regex, self).__init__(value, description=description)
pat = self.value[len("/") : -len("/")]
flags = re.DOTALL
if value.endswith("/i"):
pat = self.value[len("/") : -len("/i")]
flags |= re.IGNORECASE
try:
self.re = re.compile(pat, flags)
except re.error:
if value.endswith("/i"):
value = value[: -len("i")]
raise ValueError(
"invalid regular expression: %s it should use Python syntax, try it at https://pythex.org" % value
)
self.match = None
def evaluate(self, ctx):
for feature, locations in ctx.items():
if not isinstance(feature, (capa.features.String,)):
continue
# `re.search` finds a match anywhere in the given string
# which implies leading and/or trailing whitespace.
# using this mode cleans is more convenient for rule authors,
# so that they don't have to prefix/suffix their terms like: /.*foo.*/.
if self.re.search(feature.value):
self.match = feature.value
return capa.engine.Result(True, self, [], locations=locations)
return capa.engine.Result(False, self, [])
def __str__(self):
return 'regex(string =~ %s, matched = "%s")' % (self.value, self.match)
class StringFactory(object):
def __new__(self, value, description=None):
if value.startswith("/") and (value.endswith("/") or value.endswith("/i")):
return Regex(value, description=description)
return String(value, description=description)
class Bytes(Feature):
def __init__(self, value, description=None):
super(Bytes, self).__init__(value, description=description)
def evaluate(self, ctx):
for feature, locations in ctx.items():
if not isinstance(feature, (capa.features.Bytes,)):
continue
if feature.value.startswith(self.value):
return capa.engine.Result(True, self, [], locations=locations)
return capa.engine.Result(False, self, [])
def get_value_str(self):
return hex_string(bytes_to_str(self.value))
def freeze_serialize(self):
return (self.__class__.__name__, [bytes_to_str(self.value).upper()])
@classmethod
def freeze_deserialize(cls, args):
return cls(*[codecs.decode(x, "hex") for x in args])

222
capa/features/address.py Normal file
View File

@@ -0,0 +1,222 @@
# 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 abc
class Address(abc.ABC):
@abc.abstractmethod
def __eq__(self, other):
...
@abc.abstractmethod
def __lt__(self, other):
# implement < so that addresses can be sorted from low to high
...
@abc.abstractmethod
def __hash__(self):
# implement hash so that addresses can be used in sets and dicts
...
@abc.abstractmethod
def __repr__(self):
# implement repr to help during debugging
...
class AbsoluteVirtualAddress(int, Address):
"""an absolute memory address"""
def __new__(cls, v):
assert v >= 0
return int.__new__(cls, v)
def __repr__(self):
return f"absolute(0x{self:x})"
def __hash__(self):
return int.__hash__(self)
class ProcessAddress(Address):
"""an address of a process in a dynamic execution trace"""
def __init__(self, pid: int, ppid: int = 0):
assert ppid >= 0
assert pid > 0
self.ppid = ppid
self.pid = pid
def __repr__(self):
return "process(%s%s)" % (
f"ppid: {self.ppid}, " if self.ppid > 0 else "",
f"pid: {self.pid}",
)
def __hash__(self):
return hash((self.ppid, self.pid))
def __eq__(self, other):
assert isinstance(other, ProcessAddress)
return (self.ppid, self.pid) == (other.ppid, other.pid)
def __lt__(self, other):
assert isinstance(other, ProcessAddress)
return (self.ppid, self.pid) < (other.ppid, other.pid)
class ThreadAddress(Address):
"""addresses a thread in a dynamic execution trace"""
def __init__(self, process: ProcessAddress, tid: int):
assert tid >= 0
self.process = process
self.tid = tid
def __repr__(self):
return f"{self.process}, thread(tid: {self.tid})"
def __hash__(self):
return hash((self.process, self.tid))
def __eq__(self, other):
assert isinstance(other, ThreadAddress)
return (self.process, self.tid) == (other.process, other.tid)
def __lt__(self, other):
assert isinstance(other, ThreadAddress)
return (self.process, self.tid) < (other.process, other.tid)
class DynamicCallAddress(Address):
"""addesses a call in a dynamic execution trace"""
def __init__(self, thread: ThreadAddress, id: int):
assert id >= 0
self.thread = thread
self.id = id
def __repr__(self):
return f"{self.thread}, call(id: {self.id})"
def __hash__(self):
return hash((self.thread, self.id))
def __eq__(self, other):
assert isinstance(other, DynamicCallAddress)
return (self.thread, self.id) == (other.thread, other.id)
def __lt__(self, other):
assert isinstance(other, DynamicCallAddress)
return (self.thread, self.id) < (other.thread, other.id)
class RelativeVirtualAddress(int, Address):
"""a memory address relative to a base address"""
def __repr__(self):
return f"relative(0x{self:x})"
def __hash__(self):
return int.__hash__(self)
class FileOffsetAddress(int, Address):
"""an address relative to the start of a file"""
def __new__(cls, v):
assert v >= 0
return int.__new__(cls, v)
def __repr__(self):
return f"file(0x{self:x})"
def __hash__(self):
return int.__hash__(self)
class DNTokenAddress(int, Address):
"""a .NET token"""
def __new__(cls, token: int):
return int.__new__(cls, token)
def __repr__(self):
return f"token(0x{self:x})"
def __hash__(self):
return int.__hash__(self)
class DNTokenOffsetAddress(Address):
"""an offset into an object specified by a .NET token"""
def __init__(self, token: int, offset: int):
assert offset >= 0
self.token = token
self.offset = offset
def __eq__(self, other):
return (self.token, self.offset) == (other.token, other.offset)
def __lt__(self, other):
return (self.token, self.offset) < (other.token, other.offset)
def __hash__(self):
return hash((self.token, self.offset))
def __repr__(self):
return f"token(0x{self.token:x})+(0x{self.offset:x})"
def __index__(self):
return self.token + self.offset
class DexMethodAddress(int, Address):
def __new__(cls, offset: int):
return int.__new__(cls, offset)
def __repr__(self):
return f"DexMethodAddress(offset={hex(self)})"
def __str__(self) -> str:
return repr(self)
def __hash__(self):
return int.__hash__(self)
class DexClassAddress(int, Address):
def __new__(cls, offset: int):
return int.__new__(cls, offset)
def __repr__(self):
return f"DexClassAddress(offset={hex(self)})"
def __str__(self) -> str:
return repr(self)
def __hash__(self):
return int.__hash__(self)
class _NoAddress(Address):
def __eq__(self, other):
return True
def __lt__(self, other):
return False
def __hash__(self):
return hash(0)
def __repr__(self):
return "no address"
NO_ADDRESS = _NoAddress()

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2020 FireEye, 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
@@ -6,22 +6,15 @@
# 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 capa.features import Feature
from capa.features.common import Feature
class BasicBlock(Feature):
def __init__(self):
super(BasicBlock, self).__init__(None)
def __init__(self, description=None):
super().__init__(0, description=description)
def __str__(self):
return "basic block"
def get_value_str(self):
return ""
def freeze_serialize(self):
return (self.__class__.__name__, [])
@classmethod
def freeze_deserialize(cls, args):
return cls()

492
capa/features/common.py Normal file
View File

@@ -0,0 +1,492 @@
# 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 re
import abc
import codecs
import typing
import logging
import collections
from typing import TYPE_CHECKING, Set, Dict, List, Union, Optional
if TYPE_CHECKING:
# circular import, otherwise
import capa.engine
import capa.perf
import capa.features
import capa.features.extractors.elf
from capa.features.address import Address
logger = logging.getLogger(__name__)
MAX_BYTES_FEATURE_SIZE = 0x100
# thunks may be chained so we specify a delta to control the depth to which these chains are explored
THUNK_CHAIN_DEPTH_DELTA = 5
class FeatureAccess:
READ = "read"
WRITE = "write"
VALID_FEATURE_ACCESS = (FeatureAccess.READ, FeatureAccess.WRITE)
def bytes_to_str(b: bytes) -> str:
return str(codecs.encode(b, "hex").decode("utf-8"))
def hex_string(h: str) -> str:
"""render hex string e.g. "0a40b1" as "0A 40 B1" """
return " ".join(h[i : i + 2] for i in range(0, len(h), 2)).upper()
def escape_string(s: str) -> str:
"""escape special characters"""
s = repr(s)
if not s.startswith(('"', "'")):
# u'hello\r\nworld' -> hello\\r\\nworld
s = s[2:-1]
else:
# 'hello\r\nworld' -> hello\\r\\nworld
s = s[1:-1]
s = s.replace("\\'", "'") # repr() may escape "'" in some edge cases, remove
s = s.replace('"', '\\"') # repr() does not escape '"', add
return s
class Result:
"""
represents the results of an evaluation of statements against features.
instances of this class should behave like a bool,
e.g. `assert Result(True, ...) == True`
instances track additional metadata about evaluation results.
they contain references to the statement node (e.g. an And statement),
as well as the children Result instances.
we need this so that we can render the tree of expressions and their results.
"""
def __init__(
self,
success: bool,
statement: Union["capa.engine.Statement", "Feature"],
children: List["Result"],
locations: Optional[Set[Address]] = None,
):
super().__init__()
self.success = success
self.statement = statement
self.children = children
self.locations = locations if locations is not None else set()
def __eq__(self, other):
if isinstance(other, bool):
return self.success == other
return False
def __bool__(self):
return self.success
def __nonzero__(self):
return self.success
class Feature(abc.ABC): # noqa: B024
# this is an abstract class, since we don't want anyone to instantiate it directly,
# but it doesn't have any abstract methods.
def __init__(
self,
value: Union[str, int, float, bytes],
description: Optional[str] = None,
):
"""
Args:
value (any): the value of the feature, such as the number or string.
description (str): a human-readable description that explains the feature value.
"""
super().__init__()
self.name = self.__class__.__name__.lower()
self.value = value
self.description = description
def __hash__(self):
return hash((self.name, self.value))
def __eq__(self, other):
return self.name == other.name and self.value == other.value
def __lt__(self, other):
# implementing sorting by serializing to JSON is a huge hack.
# its slow, inelegant, and probably doesn't work intuitively;
# however, we only use it for deterministic output, so it's good enough for now.
# circular import
# we should fix if this wasn't already a huge hack.
import capa.features.freeze.features
return (
capa.features.freeze.features.feature_from_capa(self).model_dump_json()
< capa.features.freeze.features.feature_from_capa(other).model_dump_json()
)
def get_name_str(self) -> str:
"""
render the name of this feature, for use by `__str__` and friends.
subclasses should override to customize the rendering.
"""
return self.name
def get_value_str(self) -> str:
"""
render the value of this feature, for use by `__str__` and friends.
subclasses should override to customize the rendering.
"""
return str(self.value)
def __str__(self):
if self.value is not None:
if self.description:
return f"{self.get_name_str()}({self.get_value_str()} = {self.description})"
else:
return f"{self.get_name_str()}({self.get_value_str()})"
else:
return f"{self.get_name_str()}"
def __repr__(self):
return str(self)
def evaluate(self, ctx: Dict["Feature", Set[Address]], **kwargs) -> Result:
capa.perf.counters["evaluate.feature"] += 1
capa.perf.counters["evaluate.feature." + self.name] += 1
return Result(self in ctx, self, [], locations=ctx.get(self, set()))
class MatchedRule(Feature):
def __init__(self, value: str, description=None):
super().__init__(value, description=description)
self.name = "match"
class Characteristic(Feature):
def __init__(self, value: str, description=None):
super().__init__(value, description=description)
class String(Feature):
def __init__(self, value: str, description=None):
super().__init__(value, description=description)
def get_value_str(self) -> str:
assert isinstance(self.value, str)
return escape_string(self.value)
class Class(Feature):
def __init__(self, value: str, description=None):
super().__init__(value, description=description)
class Namespace(Feature):
def __init__(self, value: str, description=None):
super().__init__(value, description=description)
class Substring(String):
def __init__(self, value: str, description=None):
super().__init__(value, description=description)
self.value = value
def evaluate(self, ctx, short_circuit=True):
capa.perf.counters["evaluate.feature"] += 1
capa.perf.counters["evaluate.feature.substring"] += 1
# mapping from string value to list of locations.
# will unique the locations later on.
matches: typing.DefaultDict[str, Set[Address]] = collections.defaultdict(set)
assert isinstance(self.value, str)
for feature, locations in ctx.items():
if not isinstance(feature, (String,)):
continue
if not isinstance(feature.value, str):
# this is a programming error: String should only contain str
raise ValueError("unexpected feature value type")
if self.value in feature.value:
matches[feature.value].update(locations)
if short_circuit:
# we found one matching string, thats sufficient to match.
# don't collect other matching strings in this mode.
break
if matches:
# collect all locations
locations = set()
for locs in matches.values():
locations.update(locs)
# unlike other features, we cannot return put a reference to `self` directly in a `Result`.
# this is because `self` may match on many strings, so we can't stuff the matched value into it.
# instead, return a new instance that has a reference to both the substring and the matched values.
return Result(True, _MatchedSubstring(self, dict(matches)), [], locations=locations)
else:
return Result(False, _MatchedSubstring(self, {}), [])
def get_value_str(self) -> str:
assert isinstance(self.value, str)
return escape_string(self.value)
def __str__(self):
assert isinstance(self.value, str)
return f"substring({escape_string(self.value)})"
class _MatchedSubstring(Substring):
"""
this represents specific match instances of a substring feature.
treat it the same as a `Substring` except it has the `matches` field that contains the complete strings that matched.
note: this type should only ever be constructed by `Substring.evaluate()`. it is not part of the public API.
"""
def __init__(self, substring: Substring, matches: Dict[str, Set[Address]]):
"""
args:
substring: the substring feature that matches.
match: mapping from matching string to its locations.
"""
super().__init__(str(substring.value), description=substring.description)
# we want this to collide with the name of `Substring` above,
# so that it works nicely with the renderers.
self.name = "substring"
# this may be None if the substring doesn't match
self.matches = matches
def __str__(self):
matches = ", ".join(f'"{s}"' for s in (self.matches or {}).keys())
assert isinstance(self.value, str)
return f'substring("{self.value}", matches = {matches})'
class Regex(String):
def __init__(self, value: str, description=None):
super().__init__(value, description=description)
self.value = value
pat = self.value[len("/") : -len("/")]
flags = re.DOTALL
if value.endswith("/i"):
pat = self.value[len("/") : -len("/i")]
flags |= re.IGNORECASE
try:
self.re = re.compile(pat, flags)
except re.error as exc:
if value.endswith("/i"):
value = value[: -len("i")]
raise ValueError(
f"invalid regular expression: {value} it should use Python syntax, try it at https://pythex.org"
) from exc
def evaluate(self, ctx, short_circuit=True):
capa.perf.counters["evaluate.feature"] += 1
capa.perf.counters["evaluate.feature.regex"] += 1
# mapping from string value to list of locations.
# will unique the locations later on.
matches: typing.DefaultDict[str, Set[Address]] = collections.defaultdict(set)
for feature, locations in ctx.items():
if not isinstance(feature, (String,)):
continue
if not isinstance(feature.value, str):
# this is a programming error: String should only contain str
raise ValueError("unexpected feature value type")
# `re.search` finds a match anywhere in the given string
# which implies leading and/or trailing whitespace.
# using this mode cleans is more convenient for rule authors,
# so that they don't have to prefix/suffix their terms like: /.*foo.*/.
if self.re.search(feature.value):
matches[feature.value].update(locations)
if short_circuit:
# we found one matching string, thats sufficient to match.
# don't collect other matching strings in this mode.
break
if matches:
# collect all locations
locations = set()
for locs in matches.values():
locations.update(locs)
# unlike other features, we cannot return put a reference to `self` directly in a `Result`.
# this is because `self` may match on many strings, so we can't stuff the matched value into it.
# instead, return a new instance that has a reference to both the regex and the matched values.
# see #262.
return Result(True, _MatchedRegex(self, dict(matches)), [], locations=locations)
else:
return Result(False, _MatchedRegex(self, {}), [])
def __str__(self):
assert isinstance(self.value, str)
return f"regex(string =~ {self.value})"
class _MatchedRegex(Regex):
"""
this represents specific match instances of a regular expression feature.
treat it the same as a `Regex` except it has the `matches` field that contains the complete strings that matched.
note: this type should only ever be constructed by `Regex.evaluate()`. it is not part of the public API.
"""
def __init__(self, regex: Regex, matches: Dict[str, Set[Address]]):
"""
args:
regex: the regex feature that matches.
matches: mapping from matching string to its locations.
"""
super().__init__(str(regex.value), description=regex.description)
# we want this to collide with the name of `Regex` above,
# so that it works nicely with the renderers.
self.name = "regex"
# this may be None if the regex doesn't match
self.matches = matches
def __str__(self):
matches = ", ".join(f'"{s}"' for s in (self.matches or {}).keys())
assert isinstance(self.value, str)
return f"regex(string =~ {self.value}, matches = {matches})"
class StringFactory:
def __new__(cls, value: str, description=None):
if value.startswith("/") and (value.endswith("/") or value.endswith("/i")):
return Regex(value, description=description)
return String(value, description=description)
class Bytes(Feature):
def __init__(self, value: bytes, description=None):
super().__init__(value, description=description)
self.value = value
def evaluate(self, ctx, **kwargs):
capa.perf.counters["evaluate.feature"] += 1
capa.perf.counters["evaluate.feature.bytes"] += 1
assert isinstance(self.value, bytes)
for feature, locations in ctx.items():
if not isinstance(feature, (Bytes,)):
continue
assert isinstance(feature.value, bytes)
if feature.value.startswith(self.value):
return Result(True, self, [], locations=locations)
return Result(False, self, [])
def get_value_str(self):
assert isinstance(self.value, bytes)
return hex_string(bytes_to_str(self.value))
# other candidates here: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#machine-types
ARCH_I386 = "i386"
ARCH_AMD64 = "amd64"
# dotnet
ARCH_ANY = "any"
# dex
ARCH_DALVIK = "dalvik"
VALID_ARCH = (ARCH_I386, ARCH_AMD64, ARCH_ANY, ARCH_DALVIK)
class Arch(Feature):
def __init__(self, value: str, description=None):
super().__init__(value, description=description)
self.name = "arch"
OS_WINDOWS = "windows"
OS_LINUX = "linux"
OS_MACOS = "macos"
OS_ANDROID = "android"
# dotnet
OS_ANY = "any"
VALID_OS = {os.value for os in capa.features.extractors.elf.OS}
VALID_OS.update({OS_WINDOWS, OS_LINUX, OS_MACOS, OS_ANY, OS_ANDROID})
# internal only, not to be used in rules
OS_AUTO = "auto"
class OS(Feature):
def __init__(self, value: str, description=None):
super().__init__(value, description=description)
self.name = "os"
def evaluate(self, ctx, **kwargs):
capa.perf.counters["evaluate.feature"] += 1
capa.perf.counters["evaluate.feature." + self.name] += 1
for feature, locations in ctx.items():
if not isinstance(feature, (OS,)):
continue
assert isinstance(feature.value, str)
if OS_ANY in (self.value, feature.value) or self.value == feature.value:
return Result(True, self, [], locations=locations)
return Result(False, self, [])
FORMAT_PE = "pe"
FORMAT_ELF = "elf"
FORMAT_DOTNET = "dotnet"
FORMAT_DEX = "dex"
VALID_FORMAT = (FORMAT_PE, FORMAT_ELF, FORMAT_DOTNET, FORMAT_DEX)
# internal only, not to be used in rules
FORMAT_AUTO = "auto"
FORMAT_SC32 = "sc32"
FORMAT_SC64 = "sc64"
FORMAT_CAPE = "cape"
STATIC_FORMATS = {
FORMAT_SC32,
FORMAT_SC64,
FORMAT_PE,
FORMAT_ELF,
FORMAT_DOTNET,
FORMAT_DEX,
}
DYNAMIC_FORMATS = {
FORMAT_CAPE,
}
FORMAT_FREEZE = "freeze"
FORMAT_RESULT = "result"
FORMAT_UNKNOWN = "unknown"
class Format(Feature):
def __init__(self, value: str, description=None):
super().__init__(value, description=description)
self.name = "format"
def is_global_feature(feature):
"""
is this a feature that is extracted at every scope?
today, these are OS and arch features.
"""
return isinstance(feature, (OS, Arch))

View File

@@ -1,286 +0,0 @@
# Copyright (C) 2020 FireEye, 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 abc
class FeatureExtractor(object):
"""
FeatureExtractor defines the interface for fetching features from a sample.
There may be multiple backends that support fetching features for capa.
For example, we use vivisect by default, but also want to support saving
and restoring features from a JSON file.
When we restore the features, we'd like to use exactly the same matching logic
to find matching rules.
Therefore, we can define a FeatureExtractor that provides features from the
serialized JSON file and do matching without a binary analysis pass.
Also, this provides a way to hook in an IDA backend.
This class is not instantiated directly; it is the base class for other implementations.
"""
__metaclass__ = abc.ABCMeta
def __init__(self):
#
# note: a subclass should define ctor parameters for its own use.
# for example, the Vivisect feature extract might require the vw and/or path.
# this base class doesn't know what to do with that info, though.
#
super(FeatureExtractor, self).__init__()
@abc.abstractmethod
def get_base_address(self):
"""
fetch the preferred load address at which the sample was analyzed.
returns: int
"""
raise NotImplemented
@abc.abstractmethod
def extract_file_features(self):
"""
extract file-scope features.
example::
extractor = VivisectFeatureExtractor(vw, path)
for feature, va in extractor.get_file_features():
print('0x%x: %s', va, feature)
yields:
Tuple[capa.features.Feature, int]: feature and its location
"""
raise NotImplemented
@abc.abstractmethod
def get_functions(self):
"""
enumerate the functions and provide opaque values that will
subsequently be provided to `.extract_function_features()`, etc.
by "opaque value", we mean that this can be any object, as long as it
provides enough context to `.extract_function_features()`.
the opaque value should support casting to int (`__int__`) for the function start address.
yields:
any: the opaque function value.
"""
raise NotImplemented
@abc.abstractmethod
def extract_function_features(self, f):
"""
extract function-scope features.
the arguments are opaque values previously provided by `.get_functions()`, etc.
example::
extractor = VivisectFeatureExtractor(vw, path)
for function in extractor.get_functions():
for feature, va in extractor.extract_function_features(function):
print('0x%x: %s', va, feature)
args:
f [any]: an opaque value previously fetched from `.get_functions()`.
yields:
Tuple[capa.features.Feature, int]: feature and its location
"""
raise NotImplemented
@abc.abstractmethod
def get_basic_blocks(self, f):
"""
enumerate the basic blocks in the given function and provide opaque values that will
subsequently be provided to `.extract_basic_block_features()`, etc.
by "opaque value", we mean that this can be any object, as long as it
provides enough context to `.extract_basic_block_features()`.
the opaque value should support casting to int (`__int__`) for the basic block start address.
yields:
any: the opaque basic block value.
"""
raise NotImplemented
@abc.abstractmethod
def extract_basic_block_features(self, f, bb):
"""
extract basic block-scope features.
the arguments are opaque values previously provided by `.get_functions()`, etc.
example::
extractor = VivisectFeatureExtractor(vw, path)
for function in extractor.get_functions():
for bb in extractor.get_basic_blocks(function):
for feature, va in extractor.extract_basic_block_features(function, bb):
print('0x%x: %s', va, feature)
args:
f [any]: an opaque value previously fetched from `.get_functions()`.
bb [any]: an opaque value previously fetched from `.get_basic_blocks()`.
yields:
Tuple[capa.features.Feature, int]: feature and its location
"""
raise NotImplemented
@abc.abstractmethod
def get_instructions(self, f, bb):
"""
enumerate the instructions in the given basic block and provide opaque values that will
subsequently be provided to `.extract_insn_features()`, etc.
by "opaque value", we mean that this can be any object, as long as it
provides enough context to `.extract_insn_features()`.
the opaque value should support casting to int (`__int__`) for the instruction address.
yields:
any: the opaque function value.
"""
raise NotImplemented
@abc.abstractmethod
def extract_insn_features(self, f, bb, insn):
"""
extract instruction-scope features.
the arguments are opaque values previously provided by `.get_functions()`, etc.
example::
extractor = VivisectFeatureExtractor(vw, path)
for function in extractor.get_functions():
for bb in extractor.get_basic_blocks(function):
for insn in extractor.get_instructions(function, bb):
for feature, va in extractor.extract_insn_features(function, bb, insn):
print('0x%x: %s', va, feature)
args:
f [any]: an opaque value previously fetched from `.get_functions()`.
bb [any]: an opaque value previously fetched from `.get_basic_blocks()`.
insn [any]: an opaque value previously fetched from `.get_instructions()`.
yields:
Tuple[capa.features.Feature, int]: feature and its location
"""
raise NotImplemented
class NullFeatureExtractor(FeatureExtractor):
"""
An extractor that extracts some user-provided features.
The structure of the single parameter is demonstrated in the example below.
This is useful for testing, as we can provide expected values and see if matching works.
Also, this is how we represent features deserialized from a freeze file.
example::
extractor = NullFeatureExtractor({
'base address: 0x401000,
'file features': [
(0x402345, capa.features.Characteristic('embedded pe')),
],
'functions': {
0x401000: {
'features': [
(0x401000, capa.features.Characteristic('nzxor')),
],
'basic blocks': {
0x401000: {
'features': [
(0x401000, capa.features.Characteristic('tight-loop')),
],
'instructions': {
0x401000: {
'features': [
(0x401000, capa.features.Characteristic('nzxor')),
],
},
0x401002: ...
}
},
0x401005: ...
}
},
0x40200: ...
}
)
"""
def __init__(self, features):
super(NullFeatureExtractor, self).__init__()
self.features = features
def get_base_address(self):
return self.features["base address"]
def extract_file_features(self):
for p in self.features.get("file features", []):
va, feature = p
yield feature, va
def get_functions(self):
for va in sorted(self.features["functions"].keys()):
yield va
def extract_function_features(self, f):
for p in self.features.get("functions", {}).get(f, {}).get("features", []): # noqa: E127 line over-indented
va, feature = p
yield feature, va
def get_basic_blocks(self, f):
for va in sorted(
self.features.get("functions", {}) # noqa: E127 line over-indented
.get(f, {})
.get("basic blocks", {})
.keys()
):
yield va
def extract_basic_block_features(self, f, bb):
for p in (
self.features.get("functions", {}) # noqa: E127 line over-indented
.get(f, {})
.get("basic blocks", {})
.get(bb, {})
.get("features", [])
):
va, feature = p
yield feature, va
def get_instructions(self, f, bb):
for va in sorted(
self.features.get("functions", {}) # noqa: E127 line over-indented
.get(f, {})
.get("basic blocks", {})
.get(bb, {})
.get("instructions", {})
.keys()
):
yield va
def extract_insn_features(self, f, bb, insn):
for p in (
self.features.get("functions", {}) # noqa: E127 line over-indented
.get(f, {})
.get("basic blocks", {})
.get(bb, {})
.get("instructions", {})
.get(insn, {})
.get("features", [])
):
va, feature = p
yield feature, va

View File

@@ -0,0 +1,470 @@
# 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 abc
import hashlib
import dataclasses
from typing import Any, Dict, Tuple, Union, Iterator
from dataclasses import dataclass
# TODO(williballenthin): use typing.TypeAlias directly when Python 3.9 is deprecated
# https://github.com/mandiant/capa/issues/1699
from typing_extensions import TypeAlias
import capa.features.address
from capa.features.common import Feature
from capa.features.address import Address, ThreadAddress, ProcessAddress, DynamicCallAddress, AbsoluteVirtualAddress
# feature extractors may reference functions, BBs, insns by opaque handle values.
# you can use the `.address` property to get and render the address of the feature.
#
# these handles are only consumed by routines on
# the feature extractor from which they were created.
@dataclass
class SampleHashes:
md5: str
sha1: str
sha256: str
@classmethod
def from_bytes(cls, buf: bytes) -> "SampleHashes":
md5 = hashlib.md5()
sha1 = hashlib.sha1()
sha256 = hashlib.sha256()
md5.update(buf)
sha1.update(buf)
sha256.update(buf)
return cls(md5=md5.hexdigest(), sha1=sha1.hexdigest(), sha256=sha256.hexdigest())
@dataclass
class FunctionHandle:
"""reference to a function recognized by a feature extractor.
Attributes:
address: the address of the function.
inner: extractor-specific data.
ctx: a context object for the extractor.
"""
address: Address
inner: Any
ctx: Dict[str, Any] = dataclasses.field(default_factory=dict)
@dataclass
class BBHandle:
"""reference to a basic block recognized by a feature extractor.
Attributes:
address: the address of the basic block start address.
inner: extractor-specific data.
"""
address: Address
inner: Any
@dataclass
class InsnHandle:
"""reference to a instruction recognized by a feature extractor.
Attributes:
address: the address of the instruction address.
inner: extractor-specific data.
"""
address: Address
inner: Any
class StaticFeatureExtractor:
"""
StaticFeatureExtractor defines the interface for fetching features from a
sample without running it; extractors that rely on the execution trace of
a sample must implement the other sibling class, DynamicFeatureExtracor.
There may be multiple backends that support fetching features for capa.
For example, we use vivisect by default, but also want to support saving
and restoring features from a JSON file.
When we restore the features, we'd like to use exactly the same matching logic
to find matching rules.
Therefore, we can define a StaticFeatureExtractor that provides features from the
serialized JSON file and do matching without a binary analysis pass.
Also, this provides a way to hook in an IDA backend.
This class is not instantiated directly; it is the base class for other implementations.
"""
__metaclass__ = abc.ABCMeta
def __init__(self, hashes: SampleHashes):
#
# note: a subclass should define ctor parameters for its own use.
# for example, the Vivisect feature extract might require the vw and/or path.
# this base class doesn't know what to do with that info, though.
#
super().__init__()
self._sample_hashes = hashes
@abc.abstractmethod
def get_base_address(self) -> Union[AbsoluteVirtualAddress, capa.features.address._NoAddress]:
"""
fetch the preferred load address at which the sample was analyzed.
when the base address is `NO_ADDRESS`, then the loader has no concept of a preferred load address.
such as: shellcode, .NET modules, etc.
in these scenarios, RelativeVirtualAddresses aren't used.
"""
raise NotImplementedError()
def get_sample_hashes(self) -> SampleHashes:
"""
fetch the hashes for the sample contained within the extractor.
"""
return self._sample_hashes
@abc.abstractmethod
def extract_global_features(self) -> Iterator[Tuple[Feature, Address]]:
"""
extract features found at every scope ("global").
example::
extractor = VivisectFeatureExtractor(vw, path)
for feature, va in extractor.get_global_features():
print('0x%x: %s', va, feature)
yields:
Tuple[Feature, Address]: feature and its location
"""
raise NotImplementedError()
@abc.abstractmethod
def extract_file_features(self) -> Iterator[Tuple[Feature, Address]]:
"""
extract file-scope features.
example::
extractor = VivisectFeatureExtractor(vw, path)
for feature, va in extractor.get_file_features():
print('0x%x: %s', va, feature)
yields:
Tuple[Feature, Address]: feature and its location
"""
raise NotImplementedError()
@abc.abstractmethod
def get_functions(self) -> Iterator[FunctionHandle]:
"""
enumerate the functions and provide opaque values that will
subsequently be provided to `.extract_function_features()`, etc.
"""
raise NotImplementedError()
def is_library_function(self, addr: Address) -> bool:
"""
is the given address a library function?
the backend may implement its own function matching algorithm, or none at all.
we accept an address here, rather than function object,
to handle addresses identified in instructions.
this information is used to:
- filter out matches in library functions (by default), and
- recognize when to fetch symbol names for called (non-API) functions
args:
addr (Address): the address of a function.
returns:
bool: True if the given address is the start of a library function.
"""
return False
def get_function_name(self, addr: Address) -> str:
"""
fetch any recognized name for the given address.
this is only guaranteed to return a value when the given function is a recognized library function.
we accept a VA here, rather than function object, to handle addresses identified in instructions.
args:
addr (Address): the address of a function.
returns:
str: the function name
raises:
KeyError: when the given function does not have a name.
"""
raise KeyError(addr)
@abc.abstractmethod
def extract_function_features(self, f: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
"""
extract function-scope features.
the arguments are opaque values previously provided by `.get_functions()`, etc.
example::
extractor = VivisectFeatureExtractor(vw, path)
for function in extractor.get_functions():
for feature, address in extractor.extract_function_features(function):
print('0x%x: %s', address, feature)
args:
f [FunctionHandle]: an opaque value previously fetched from `.get_functions()`.
yields:
Tuple[Feature, Address]: feature and its location
"""
raise NotImplementedError()
@abc.abstractmethod
def get_basic_blocks(self, f: FunctionHandle) -> Iterator[BBHandle]:
"""
enumerate the basic blocks in the given function and provide opaque values that will
subsequently be provided to `.extract_basic_block_features()`, etc.
"""
raise NotImplementedError()
@abc.abstractmethod
def extract_basic_block_features(self, f: FunctionHandle, bb: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""
extract basic block-scope features.
the arguments are opaque values previously provided by `.get_functions()`, etc.
example::
extractor = VivisectFeatureExtractor(vw, path)
for function in extractor.get_functions():
for bb in extractor.get_basic_blocks(function):
for feature, address in extractor.extract_basic_block_features(function, bb):
print('0x%x: %s', address, feature)
args:
f [FunctionHandle]: an opaque value previously fetched from `.get_functions()`.
bb [BBHandle]: an opaque value previously fetched from `.get_basic_blocks()`.
yields:
Tuple[Feature, Address]: feature and its location
"""
raise NotImplementedError()
@abc.abstractmethod
def get_instructions(self, f: FunctionHandle, bb: BBHandle) -> Iterator[InsnHandle]:
"""
enumerate the instructions in the given basic block and provide opaque values that will
subsequently be provided to `.extract_insn_features()`, etc.
"""
raise NotImplementedError()
@abc.abstractmethod
def extract_insn_features(
self, f: FunctionHandle, bb: BBHandle, insn: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
extract instruction-scope features.
the arguments are opaque values previously provided by `.get_functions()`, etc.
example::
extractor = VivisectFeatureExtractor(vw, path)
for function in extractor.get_functions():
for bb in extractor.get_basic_blocks(function):
for insn in extractor.get_instructions(function, bb):
for feature, address in extractor.extract_insn_features(function, bb, insn):
print('0x%x: %s', address, feature)
args:
f [FunctionHandle]: an opaque value previously fetched from `.get_functions()`.
bb [BBHandle]: an opaque value previously fetched from `.get_basic_blocks()`.
insn [InsnHandle]: an opaque value previously fetched from `.get_instructions()`.
yields:
Tuple[Feature, Address]: feature and its location
"""
raise NotImplementedError()
@dataclass
class ProcessHandle:
"""
reference to a process extracted by the sandbox.
Attributes:
address: process's address (pid)
inner: sandbox-specific data
"""
address: ProcessAddress
inner: Any
@dataclass
class ThreadHandle:
"""
reference to a thread extracted by the sandbox.
Attributes:
address: thread's address (tid)
inner: sandbox-specific data
"""
address: ThreadAddress
inner: Any
@dataclass
class CallHandle:
"""
reference to an api call extracted by the sandbox.
Attributes:
address: call's address, such as event index or id
inner: sandbox-specific data
"""
address: DynamicCallAddress
inner: Any
class DynamicFeatureExtractor:
"""
DynamicFeatureExtractor defines the interface for fetching features from a
sandbox' analysis of a sample; extractors that rely on statically analyzing
a sample must implement the sibling extractor, StaticFeatureExtractor.
Features are grouped mainly into threads that alongside their meta-features are also grouped into
processes (that also have their own features). Other scopes (such as function and file) may also apply
for a specific sandbox.
This class is not instantiated directly; it is the base class for other implementations.
"""
__metaclass__ = abc.ABCMeta
def __init__(self, hashes: SampleHashes):
#
# note: a subclass should define ctor parameters for its own use.
# for example, the Vivisect feature extract might require the vw and/or path.
# this base class doesn't know what to do with that info, though.
#
super().__init__()
self._sample_hashes = hashes
def get_sample_hashes(self) -> SampleHashes:
"""
fetch the hashes for the sample contained within the extractor.
"""
return self._sample_hashes
@abc.abstractmethod
def extract_global_features(self) -> Iterator[Tuple[Feature, Address]]:
"""
extract features found at every scope ("global").
example::
extractor = CapeFeatureExtractor.from_report(json.loads(buf))
for feature, addr in extractor.get_global_features():
print(addr, feature)
yields:
Tuple[Feature, Address]: feature and its location
"""
raise NotImplementedError()
@abc.abstractmethod
def extract_file_features(self) -> Iterator[Tuple[Feature, Address]]:
"""
extract file-scope features.
example::
extractor = CapeFeatureExtractor.from_report(json.loads(buf))
for feature, addr in extractor.get_file_features():
print(addr, feature)
yields:
Tuple[Feature, Address]: feature and its location
"""
raise NotImplementedError()
@abc.abstractmethod
def get_processes(self) -> Iterator[ProcessHandle]:
"""
Enumerate processes in the trace.
"""
raise NotImplementedError()
@abc.abstractmethod
def extract_process_features(self, ph: ProcessHandle) -> Iterator[Tuple[Feature, Address]]:
"""
Yields all the features of a process. These include:
- file features of the process' image
"""
raise NotImplementedError()
@abc.abstractmethod
def get_process_name(self, ph: ProcessHandle) -> str:
"""
Returns the human-readable name for the given process,
such as the filename.
"""
raise NotImplementedError()
@abc.abstractmethod
def get_threads(self, ph: ProcessHandle) -> Iterator[ThreadHandle]:
"""
Enumerate threads in the given process.
"""
raise NotImplementedError()
@abc.abstractmethod
def extract_thread_features(self, ph: ProcessHandle, th: ThreadHandle) -> Iterator[Tuple[Feature, Address]]:
"""
Yields all the features of a thread. These include:
- sequenced api traces
"""
raise NotImplementedError()
@abc.abstractmethod
def get_calls(self, ph: ProcessHandle, th: ThreadHandle) -> Iterator[CallHandle]:
"""
Enumerate calls in the given thread
"""
raise NotImplementedError()
@abc.abstractmethod
def extract_call_features(
self, ph: ProcessHandle, th: ThreadHandle, ch: CallHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
Yields all features of a call. These include:
- api name
- bytes/strings/numbers extracted from arguments
"""
raise NotImplementedError()
@abc.abstractmethod
def get_call_name(self, ph: ProcessHandle, th: ThreadHandle, ch: CallHandle) -> str:
"""
Returns the human-readable name for the given call,
such as as rendered API log entry, like:
Foo(1, "two", b"\x00\x11") -> -1
"""
raise NotImplementedError()
FeatureExtractor: TypeAlias = Union[StaticFeatureExtractor, DynamicFeatureExtractor]

View File

@@ -0,0 +1,184 @@
# 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
from binaryninja import Function, Settings
from binaryninja import BasicBlock as BinjaBasicBlock
from binaryninja import (
BinaryView,
SymbolType,
RegisterValueType,
VariableSourceType,
MediumLevelILSetVar,
MediumLevelILOperation,
MediumLevelILBasicBlock,
MediumLevelILInstruction,
)
from capa.features.common import Feature, Characteristic
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
use_const_outline: bool = False
settings: Settings = Settings()
if settings.contains("analysis.outlining.builtins") and settings.get_bool("analysis.outlining.builtins"):
use_const_outline = True
def get_printable_len_ascii(s: bytes) -> int:
"""Return string length if all operand bytes are ascii or utf16-le printable"""
count = 0
for c in s:
if c == 0:
return count
if c < 127 and chr(c) in string.printable:
count += 1
return count
def get_printable_len_wide(s: bytes) -> int:
"""Return string length if all operand bytes are ascii or utf16-le printable"""
if all(c == 0x00 for c in s[1::2]):
return get_printable_len_ascii(s[::2])
return 0
def get_stack_string_len(f: Function, il: MediumLevelILInstruction) -> int:
bv: BinaryView = f.view
if il.operation != MediumLevelILOperation.MLIL_CALL:
return 0
target = il.dest
if target.operation not in [MediumLevelILOperation.MLIL_CONST, MediumLevelILOperation.MLIL_CONST_PTR]:
return 0
addr = target.value.value
sym = bv.get_symbol_at(addr)
if not sym or sym.type != SymbolType.LibraryFunctionSymbol:
return 0
if sym.name not in ["__builtin_strncpy", "__builtin_strcpy", "__builtin_wcscpy"]:
return 0
if len(il.params) < 2:
return 0
dest = il.params[0]
if dest.operation in [MediumLevelILOperation.MLIL_ADDRESS_OF, MediumLevelILOperation.MLIL_VAR]:
var = dest.src
else:
return 0
if var.source_type != VariableSourceType.StackVariableSourceType:
return 0
src = il.params[1]
if src.value.type != RegisterValueType.ConstantDataAggregateValue:
return 0
s = f.get_constant_data(RegisterValueType.ConstantDataAggregateValue, src.value.value)
return max(get_printable_len_ascii(bytes(s)), get_printable_len_wide(bytes(s)))
def get_printable_len(il: MediumLevelILSetVar) -> int:
"""Return string length if all operand bytes are ascii or utf16-le printable"""
width = il.dest.type.width
value = il.src.value.value
if width == 1:
chars = struct.pack("<B", value & 0xFF)
elif width == 2:
chars = struct.pack("<H", value & 0xFFFF)
elif width == 4:
chars = struct.pack("<I", value & 0xFFFFFFFF)
elif width == 8:
chars = struct.pack("<Q", value & 0xFFFFFFFFFFFFFFFF)
else:
return 0
def is_printable_ascii(chars_: bytes):
return all(c < 127 and chr(c) in string.printable for c in chars_)
def is_printable_utf16le(chars_: bytes):
if all(c == 0x00 for c in chars_[1::2]):
return is_printable_ascii(chars_[::2])
if is_printable_ascii(chars):
return width
if is_printable_utf16le(chars):
return width // 2
return 0
def is_mov_imm_to_stack(il: MediumLevelILInstruction) -> bool:
"""verify instruction moves immediate onto stack"""
if il.operation != MediumLevelILOperation.MLIL_SET_VAR:
return False
if il.src.operation != MediumLevelILOperation.MLIL_CONST:
return False
if il.dest.source_type != VariableSourceType.StackVariableSourceType:
return False
return True
def bb_contains_stackstring(f: Function, bb: MediumLevelILBasicBlock) -> bool:
"""check basic block for stackstring indicators
true if basic block contains enough moves of constant bytes to the stack
"""
count = 0
for il in bb:
if use_const_outline:
count += get_stack_string_len(f, il)
else:
if is_mov_imm_to_stack(il):
count += get_printable_len(il)
if count > MIN_STACKSTRING_LEN:
return True
return False
def extract_bb_stackstring(fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""extract stackstring indicators from basic block"""
bb: Tuple[BinjaBasicBlock, MediumLevelILBasicBlock] = bbh.inner
if bb[1] is not None and bb_contains_stackstring(fh.inner, bb[1]):
yield Characteristic("stack string"), bbh.address
def extract_bb_tight_loop(fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""extract tight loop indicators from a basic block"""
bb: Tuple[BinjaBasicBlock, MediumLevelILBasicBlock] = bbh.inner
for edge in bb[0].outgoing_edges:
if edge.target.start == bb[0].start:
yield Characteristic("tight loop"), bbh.address
def extract_features(fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""extract basic block features"""
for bb_handler in BASIC_BLOCK_HANDLERS:
for feature, addr in bb_handler(fh, bbh):
yield feature, addr
yield BasicBlock(), bbh.address
BASIC_BLOCK_HANDLERS = (
extract_bb_tight_loop,
extract_bb_stackstring,
)

View File

@@ -0,0 +1,81 @@
# 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, Iterator
import binaryninja as binja
import capa.features.extractors.elf
import capa.features.extractors.binja.file
import capa.features.extractors.binja.insn
import capa.features.extractors.binja.global_
import capa.features.extractors.binja.function
import capa.features.extractors.binja.basicblock
from capa.features.common import Feature
from capa.features.address import Address, AbsoluteVirtualAddress
from capa.features.extractors.base_extractor import (
BBHandle,
InsnHandle,
SampleHashes,
FunctionHandle,
StaticFeatureExtractor,
)
class BinjaFeatureExtractor(StaticFeatureExtractor):
def __init__(self, bv: binja.BinaryView):
super().__init__(hashes=SampleHashes.from_bytes(bv.file.raw.read(0, len(bv.file.raw))))
self.bv = bv
self.global_features: List[Tuple[Feature, Address]] = []
self.global_features.extend(capa.features.extractors.binja.file.extract_file_format(self.bv))
self.global_features.extend(capa.features.extractors.binja.global_.extract_os(self.bv))
self.global_features.extend(capa.features.extractors.binja.global_.extract_arch(self.bv))
def get_base_address(self):
return AbsoluteVirtualAddress(self.bv.start)
def extract_global_features(self):
yield from self.global_features
def extract_file_features(self):
yield from capa.features.extractors.binja.file.extract_features(self.bv)
def get_functions(self) -> Iterator[FunctionHandle]:
for f in self.bv.functions:
yield FunctionHandle(address=AbsoluteVirtualAddress(f.start), inner=f)
def extract_function_features(self, fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.binja.function.extract_features(fh)
def get_basic_blocks(self, fh: FunctionHandle) -> Iterator[BBHandle]:
f: binja.Function = fh.inner
# Set up a MLIL basic block dict look up to associate the disassembly basic block with its MLIL basic block
mlil_lookup = {}
for mlil_bb in f.mlil.basic_blocks:
mlil_lookup[mlil_bb.source_block.start] = mlil_bb
for bb in f.basic_blocks:
mlil_bb = mlil_lookup.get(bb.start)
yield BBHandle(address=AbsoluteVirtualAddress(bb.start), inner=(bb, mlil_bb))
def extract_basic_block_features(self, fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.binja.basicblock.extract_features(fh, bbh)
def get_instructions(self, fh: FunctionHandle, bbh: BBHandle) -> Iterator[InsnHandle]:
import capa.features.extractors.binja.helpers as binja_helpers
bb: Tuple[binja.BasicBlock, binja.MediumLevelILBasicBlock] = bbh.inner
addr = bb[0].start
for text, length in bb[0]:
insn = binja_helpers.DisassemblyInstruction(addr, length, text)
yield InsnHandle(address=AbsoluteVirtualAddress(addr), inner=insn)
addr += length
def extract_insn_features(self, fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle):
yield from capa.features.extractors.binja.insn.extract_features(fh, bbh, ih)

View File

@@ -0,0 +1,187 @@
# 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
from binaryninja import Segment, BinaryView, SymbolType, SymbolBinding
import capa.features.extractors.common
import capa.features.extractors.helpers
import capa.features.extractors.strings
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
from capa.features.extractors.binja.helpers import read_c_string, unmangle_c_name
def check_segment_for_pe(bv: BinaryView, seg: Segment) -> Iterator[Tuple[int, int]]:
"""check segment for embedded PE
adapted for binja from:
https://github.com/vivisect/vivisect/blob/7be4037b1cecc4551b397f840405a1fc606f9b53/PE/carve.py#L19
"""
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 = []
# If this is the first segment of the binary, skip the first bytes. Otherwise, there will always be a matched
# PE at the start of the binaryview.
start = seg.start
if bv.view_type == "PE" and start == bv.start:
start += 1
for mzx, pex, i in mz_xor:
for off, _ in bv.find_all_data(start, seg.end, mzx):
todo.append((off, mzx, pex, i))
while len(todo):
off, mzx, pex, i = todo.pop()
# The MZ header has one field we will check e_lfanew is at 0x3c
e_lfanew = off + 0x3C
if seg.end < (e_lfanew + 4):
continue
newoff = struct.unpack("<I", capa.features.extractors.helpers.xor_static(bv.read(e_lfanew, 4), i))[0]
peoff = off + newoff
if seg.end < (peoff + 2):
continue
if bv.read(peoff, 2) == pex:
yield off, i
def extract_file_embedded_pe(bv: BinaryView) -> Iterator[Tuple[Feature, Address]]:
"""extract embedded PE features"""
for seg in bv.segments:
for ea, _ in check_segment_for_pe(bv, seg):
yield Characteristic("embedded pe"), FileOffsetAddress(ea)
def extract_file_export_names(bv: BinaryView) -> Iterator[Tuple[Feature, Address]]:
"""extract function exports"""
for sym in bv.get_symbols_of_type(SymbolType.FunctionSymbol):
if sym.binding in [SymbolBinding.GlobalBinding, SymbolBinding.WeakBinding]:
name = sym.short_name
yield Export(name), AbsoluteVirtualAddress(sym.address)
unmangled_name = unmangle_c_name(name)
if name != unmangled_name:
yield Export(unmangled_name), AbsoluteVirtualAddress(sym.address)
for sym in bv.get_symbols_of_type(SymbolType.DataSymbol):
if sym.binding not in [SymbolBinding.GlobalBinding]:
continue
name = sym.short_name
if not name.startswith("__forwarder_name"):
continue
# Due to https://github.com/Vector35/binaryninja-api/issues/4641, in binja version 3.5, the symbol's name
# does not contain the DLL name. As a workaround, we read the C string at the symbol's address, which contains
# both the DLL name and the function name.
# Once the above issue is closed in the next binjs stable release, we can update the code here to use the
# symbol name directly.
name = read_c_string(bv, sym.address, 1024)
forwarded_name = capa.features.extractors.helpers.reformat_forwarded_export_name(name)
yield Export(forwarded_name), AbsoluteVirtualAddress(sym.address)
yield Characteristic("forwarded export"), AbsoluteVirtualAddress(sym.address)
def extract_file_import_names(bv: BinaryView) -> 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 sym in bv.get_symbols_of_type(SymbolType.ImportAddressSymbol):
lib_name = str(sym.namespace)
addr = AbsoluteVirtualAddress(sym.address)
for name in capa.features.extractors.helpers.generate_symbols(lib_name, sym.short_name, include_dll=True):
yield Import(name), addr
ordinal = sym.ordinal
if ordinal != 0 and (lib_name != ""):
ordinal_name = f"#{ordinal}"
for name in capa.features.extractors.helpers.generate_symbols(lib_name, ordinal_name, include_dll=True):
yield Import(name), addr
def extract_file_section_names(bv: BinaryView) -> Iterator[Tuple[Feature, Address]]:
"""extract section names"""
for name, section in bv.sections.items():
yield Section(name), AbsoluteVirtualAddress(section.start)
def extract_file_strings(bv: BinaryView) -> Iterator[Tuple[Feature, Address]]:
"""extract ASCII and UTF-16 LE strings"""
for s in bv.strings:
yield String(s.value), FileOffsetAddress(s.start)
def extract_file_function_names(bv: BinaryView) -> Iterator[Tuple[Feature, Address]]:
"""
extract the names of statically-linked library functions.
"""
for sym_name in bv.symbols:
for sym in bv.symbols[sym_name]:
if sym.type not in [SymbolType.LibraryFunctionSymbol, SymbolType.FunctionSymbol]:
continue
name = sym.short_name
yield FunctionName(name), sym.address
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:]), sym.address
def extract_file_format(bv: BinaryView) -> Iterator[Tuple[Feature, Address]]:
view_type = bv.view_type
if view_type in ["PE", "COFF"]:
yield Format(FORMAT_PE), NO_ADDRESS
elif view_type == "ELF":
yield Format(FORMAT_ELF), NO_ADDRESS
elif view_type == "Raw":
# no file type to return when processing a binary file, but we want to continue processing
return
else:
raise NotImplementedError(f"unexpected file format: {view_type}")
def extract_features(bv: BinaryView) -> Iterator[Tuple[Feature, Address]]:
"""extract file features"""
for file_handler in FILE_HANDLERS:
for feature, addr in file_handler(bv):
yield feature, addr
FILE_HANDLERS = (
extract_file_export_names,
extract_file_import_names,
extract_file_strings,
extract_file_section_names,
extract_file_embedded_pe,
extract_file_function_names,
extract_file_format,
)

View File

@@ -0,0 +1,35 @@
# 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 subprocess
from pathlib import Path
# When the script gets executed as a standalone executable (via PyInstaller), `import binaryninja` does not work because
# we have excluded the binaryninja module in `pyinstaller.spec`. The trick here is to call the system Python and try
# to find out the path of the binaryninja module that has been installed.
# Note, including the binaryninja module in the `pyintaller.spec` would not work, since the binaryninja module tries to
# find the binaryninja core e.g., `libbinaryninjacore.dylib`, using a relative path. And this does not work when the
# binaryninja module is extracted by the PyInstaller.
code = r"""
from pathlib import Path
from importlib import util
spec = util.find_spec('binaryninja')
if spec is not None:
if len(spec.submodule_search_locations) > 0:
path = Path(spec.submodule_search_locations[0])
# encode the path with utf8 then convert to hex, make sure it can be read and restored properly
print(str(path.parent).encode('utf8').hex())
"""
def find_binja_path() -> Path:
raw_output = subprocess.check_output(["python", "-c", code]).decode("ascii").strip()
return Path(bytes.fromhex(raw_output).decode("utf8"))
if __name__ == "__main__":
print(find_binja_path())

View File

@@ -0,0 +1,104 @@
# 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 Tuple, Iterator
from binaryninja import Function, BinaryView, SymbolType, RegisterValueType, LowLevelILOperation
from capa.features.file import FunctionName
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
def extract_function_calls_to(fh: FunctionHandle):
"""extract callers to a function"""
func: Function = fh.inner
for caller in func.caller_sites:
# Everything that is a code reference to the current function is considered a caller, which actually includes
# many other references that are NOT a caller. For example, an instruction `push function_start` will also be
# considered a caller to the function
llil = caller.llil
if (llil is None) or llil.operation not in [
LowLevelILOperation.LLIL_CALL,
LowLevelILOperation.LLIL_CALL_STACK_ADJUST,
LowLevelILOperation.LLIL_JUMP,
LowLevelILOperation.LLIL_TAILCALL,
]:
continue
if llil.dest.value.type not in [
RegisterValueType.ImportedAddressValue,
RegisterValueType.ConstantValue,
RegisterValueType.ConstantPointerValue,
]:
continue
address = llil.dest.value.value
if address != func.start:
continue
yield Characteristic("calls to"), AbsoluteVirtualAddress(caller.address)
def extract_function_loop(fh: FunctionHandle):
"""extract loop indicators from a function"""
func: Function = fh.inner
edges = []
# construct control flow graph
for bb in func.basic_blocks:
for edge in bb.outgoing_edges:
edges.append((bb.start, edge.target.start))
if loops.has_loop(edges):
yield Characteristic("loop"), fh.address
def extract_recursive_call(fh: FunctionHandle):
"""extract recursive function call"""
func: Function = fh.inner
bv: BinaryView = func.view
if bv is None:
return
for ref in bv.get_code_refs(func.start):
if ref.function == func:
yield Characteristic("recursive call"), fh.address
def extract_function_name(fh: FunctionHandle):
"""extract function names (e.g., symtab names)"""
func: Function = fh.inner
bv: BinaryView = func.view
if bv is None:
return
for sym in bv.get_symbols(func.start):
if sym.type not in [SymbolType.LibraryFunctionSymbol, SymbolType.FunctionSymbol]:
continue
name = sym.short_name
yield FunctionName(name), sym.address
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:]), sym.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
FUNCTION_HANDLERS = (extract_function_calls_to, extract_function_loop, extract_recursive_call, extract_function_name)

View File

@@ -0,0 +1,60 @@
# 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
from typing import Tuple, Iterator
from binaryninja import BinaryView
from capa.features.common import OS, OS_MACOS, ARCH_I386, ARCH_AMD64, OS_WINDOWS, Arch, Feature
from capa.features.address import NO_ADDRESS, Address
logger = logging.getLogger(__name__)
def extract_os(bv: BinaryView) -> Iterator[Tuple[Feature, Address]]:
name = bv.platform.name
if "-" in name:
name = name.split("-")[0]
if name == "windows":
yield OS(OS_WINDOWS), NO_ADDRESS
elif name == "macos":
yield OS(OS_MACOS), NO_ADDRESS
elif name in ["linux", "freebsd", "decree"]:
yield OS(name), 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", name)
return
def extract_arch(bv: BinaryView) -> Iterator[Tuple[Feature, Address]]:
arch = bv.arch.name
if arch == "x86_64":
yield Arch(ARCH_AMD64), NO_ADDRESS
elif arch == "x86":
yield Arch(ARCH_I386), NO_ADDRESS
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", arch)
return

View File

@@ -0,0 +1,69 @@
# 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 re
from typing import List, Callable
from dataclasses import dataclass
from binaryninja import BinaryView, LowLevelILInstruction
from binaryninja.architecture import InstructionTextToken
@dataclass
class DisassemblyInstruction:
address: int
length: int
text: List[InstructionTextToken]
LLIL_VISITOR = Callable[[LowLevelILInstruction, LowLevelILInstruction, int], bool]
def visit_llil_exprs(il: LowLevelILInstruction, func: LLIL_VISITOR):
# BN does not really support operand index at the disassembly level, so use the LLIL operand index as a substitute.
# Note, this is NOT always guaranteed to be the same as disassembly operand.
for i, op in enumerate(il.operands):
if isinstance(op, LowLevelILInstruction) and func(op, il, i):
visit_llil_exprs(op, func)
def unmangle_c_name(name: str) -> str:
# https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170#FormatC
# Possible variations for BaseThreadInitThunk:
# @BaseThreadInitThunk@12
# _BaseThreadInitThunk
# _BaseThreadInitThunk@12
# It is also possible for a function to have a `Stub` appended to its name:
# _lstrlenWStub@4
# A small optimization to avoid running the regex too many times
# this still increases the unit test execution time from 170s to 200s, should be able to accelerate it
#
# TODO(xusheng): performance optimizations to improve test execution time
# https://github.com/mandiant/capa/issues/1610
if name[0] in ["@", "_"]:
match = re.match(r"^[@|_](.*?)(Stub)?(@\d+)?$", name)
if match:
return match.group(1)
return name
def read_c_string(bv: BinaryView, offset: int, max_len: int) -> str:
s: List[str] = []
while len(s) < max_len:
try:
c = bv.read(offset + len(s), 1)[0]
except Exception:
break
if c == 0:
break
s.append(chr(c))
return "".join(s)

View File

@@ -0,0 +1,586 @@
# 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, List, Tuple, Iterator, Optional
from binaryninja import Function
from binaryninja import BasicBlock as BinjaBasicBlock
from binaryninja import (
BinaryView,
ILRegister,
SymbolType,
BinaryReader,
RegisterValueType,
LowLevelILOperation,
LowLevelILInstruction,
)
import capa.features.extractors.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.binja.helpers import DisassemblyInstruction, visit_llil_exprs
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
# check if a function is a stub function to another function/symbol. The criteria is:
# 1. The function must only have one basic block
# 2. The function must only make one call/jump to another address
# If the function being checked is a stub function, returns the target address. Otherwise, return None.
def is_stub_function(bv: BinaryView, addr: int) -> Optional[int]:
funcs = bv.get_functions_at(addr)
for func in funcs:
if len(func.basic_blocks) != 1:
continue
call_count = 0
call_target = None
for il in func.llil.instructions:
if il.operation in [
LowLevelILOperation.LLIL_CALL,
LowLevelILOperation.LLIL_CALL_STACK_ADJUST,
LowLevelILOperation.LLIL_JUMP,
LowLevelILOperation.LLIL_TAILCALL,
]:
call_count += 1
if il.dest.value.type in [
RegisterValueType.ImportedAddressValue,
RegisterValueType.ConstantValue,
RegisterValueType.ConstantPointerValue,
]:
call_target = il.dest.value.value
if call_count == 1 and call_target is not None:
return call_target
return None
def extract_insn_api_features(fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""
parse instruction API features
example:
call dword [0x00473038]
"""
func: Function = fh.inner
bv: BinaryView = func.view
for llil in func.get_llils_at(ih.address):
if llil.operation in [
LowLevelILOperation.LLIL_CALL,
LowLevelILOperation.LLIL_CALL_STACK_ADJUST,
LowLevelILOperation.LLIL_JUMP,
LowLevelILOperation.LLIL_TAILCALL,
]:
if llil.dest.value.type not in [
RegisterValueType.ImportedAddressValue,
RegisterValueType.ConstantValue,
RegisterValueType.ConstantPointerValue,
]:
continue
address = llil.dest.value.value
candidate_addrs = [address]
stub_addr = is_stub_function(bv, address)
if stub_addr is not None:
candidate_addrs.append(stub_addr)
for address in candidate_addrs:
for sym in func.view.get_symbols(address):
if sym is None or sym.type not in [
SymbolType.ImportAddressSymbol,
SymbolType.ImportedFunctionSymbol,
SymbolType.FunctionSymbol,
]:
continue
sym_name = sym.short_name
lib_name = ""
import_lib = bv.lookup_imported_object_library(sym.address)
if import_lib is not None:
lib_name = import_lib[0].name
if lib_name.endswith(".dll"):
lib_name = lib_name[:-4]
elif lib_name.endswith(".so"):
lib_name = lib_name[:-3]
for name in capa.features.extractors.helpers.generate_symbols(lib_name, sym_name):
yield API(name), ih.address
if sym_name.startswith("_"):
for name in capa.features.extractors.helpers.generate_symbols(lib_name, sym_name[1:]):
yield API(name), ih.address
def extract_insn_number_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
parse instruction number features
example:
push 3136B0h ; dwControlCode
"""
func: Function = fh.inner
results: List[Tuple[Any[Number, OperandNumber], Address]] = []
def llil_checker(il: LowLevelILInstruction, parent: LowLevelILInstruction, index: int) -> bool:
if il.operation == LowLevelILOperation.LLIL_LOAD:
return False
if il.operation not in [LowLevelILOperation.LLIL_CONST, LowLevelILOperation.LLIL_CONST_PTR]:
return True
for op in parent.operands:
if isinstance(op, ILRegister) and op.name in ["esp", "ebp", "rsp", "rbp", "sp"]:
return False
elif isinstance(op, LowLevelILInstruction) and op.operation == LowLevelILOperation.LLIL_REG:
if op.src.name in ["esp", "ebp", "rsp", "rbp", "sp"]:
return False
raw_value = il.value.value
if parent.operation == LowLevelILOperation.LLIL_SUB:
raw_value = -raw_value
results.append((Number(raw_value), ih.address))
results.append((OperandNumber(index, raw_value), ih.address))
return False
for llil in func.get_llils_at(ih.address):
visit_llil_exprs(llil, llil_checker)
yield from results
def extract_insn_bytes_features(fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""
parse referenced byte sequences
example:
push offset iid_004118d4_IShellLinkA ; riid
"""
func: Function = fh.inner
bv: BinaryView = func.view
candidate_addrs = set()
llil = func.get_llil_at(ih.address)
if llil is None or llil.operation in [LowLevelILOperation.LLIL_CALL, LowLevelILOperation.LLIL_CALL_STACK_ADJUST]:
return
for ref in bv.get_code_refs_from(ih.address):
if ref == ih.address:
continue
if len(bv.get_functions_containing(ref)) > 0:
continue
candidate_addrs.add(ref)
# collect candidate address by enumerating all integers, https://github.com/Vector35/binaryninja-api/issues/3966
def llil_checker(il: LowLevelILInstruction, parent: LowLevelILInstruction, index: int) -> bool:
if il.operation in [LowLevelILOperation.LLIL_CONST, LowLevelILOperation.LLIL_CONST_PTR]:
value = il.value.value
if value > 0:
candidate_addrs.add(value)
return False
return True
for llil in func.get_llils_at(ih.address):
visit_llil_exprs(llil, llil_checker)
for addr in candidate_addrs:
extracted_bytes = bv.read(addr, MAX_BYTES_FEATURE_SIZE)
if extracted_bytes and not capa.features.extractors.helpers.all_zeros(extracted_bytes):
if bv.get_string_at(addr) is None:
# don't extract byte features for obvious strings
yield Bytes(extracted_bytes), ih.address
def extract_insn_string_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
parse instruction string features
example:
push offset aAcr ; "ACR > "
"""
func: Function = fh.inner
bv: BinaryView = func.view
candidate_addrs = set()
# collect candidate address from code refs directly
for ref in bv.get_code_refs_from(ih.address):
if ref == ih.address:
continue
if len(bv.get_functions_containing(ref)) > 0:
continue
candidate_addrs.add(ref)
# collect candidate address by enumerating all integers, https://github.com/Vector35/binaryninja-api/issues/3966
def llil_checker(il: LowLevelILInstruction, parent: LowLevelILInstruction, index: int) -> bool:
if il.operation in [LowLevelILOperation.LLIL_CONST, LowLevelILOperation.LLIL_CONST_PTR]:
value = il.value.value
if value > 0:
candidate_addrs.add(value)
return False
return True
for llil in func.get_llils_at(ih.address):
visit_llil_exprs(llil, llil_checker)
# Now we have all the candidate address, check them for string or pointer to string
br = BinaryReader(bv)
for addr in candidate_addrs:
found = bv.get_string_at(addr)
if found:
yield String(found.value), ih.address
br.seek(addr)
pointer = None
if bv.arch.address_size == 4:
pointer = br.read32()
elif bv.arch.address_size == 8:
pointer = br.read64()
if pointer is not None:
found = bv.get_string_at(pointer)
if found:
yield String(found.value), ih.address
def extract_insn_offset_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
parse instruction structure offset features
example:
.text:0040112F cmp [esi+4], ebx
"""
func: Function = fh.inner
results: List[Tuple[Any[Offset, OperandOffset], Address]] = []
address_size = func.view.arch.address_size * 8
def llil_checker(il: LowLevelILInstruction, parent: LowLevelILInstruction, index: int) -> bool:
# The most common case, read/write dereference to something like `dword [eax+0x28]`
if il.operation in [LowLevelILOperation.LLIL_ADD, LowLevelILOperation.LLIL_SUB]:
left = il.left
right = il.right
# Exclude offsets based on stack/franme pointers
if left.operation == LowLevelILOperation.LLIL_REG and left.src.name in ["esp", "ebp", "rsp", "rbp", "sp"]:
return True
if right.operation != LowLevelILOperation.LLIL_CONST:
return True
raw_value = right.value.value
# If this is not a dereference, then this must be an add and the offset must be in the range \
# [0, MAX_STRUCTURE_SIZE]. For example,
# add eax, 0x10,
# lea ebx, [eax + 1]
if parent.operation not in [LowLevelILOperation.LLIL_LOAD, LowLevelILOperation.LLIL_STORE]:
if il.operation != LowLevelILOperation.LLIL_ADD or (not 0 < raw_value < MAX_STRUCTURE_SIZE):
return False
if address_size > 0:
# BN also encodes the constant value as two's complement, we need to restore its original value
value = capa.features.extractors.helpers.twos_complement(raw_value, address_size)
else:
value = raw_value
results.append((Offset(value), ih.address))
results.append((OperandOffset(index, value), ih.address))
return False
# An edge case: for code like `push dword [esi]`, we need to generate a feature for offset 0x0
elif il.operation in [LowLevelILOperation.LLIL_LOAD, LowLevelILOperation.LLIL_STORE]:
if il.operands[0].operation == LowLevelILOperation.LLIL_REG:
results.append((Offset(0), ih.address))
results.append((OperandOffset(index, 0), ih.address))
return False
return True
for llil in func.get_llils_at(ih.address):
visit_llil_exprs(llil, llil_checker)
yield from results
def is_nzxor_stack_cookie(f: Function, bb: BinjaBasicBlock, llil: LowLevelILInstruction) -> bool:
"""check if nzxor exists within stack cookie delta"""
# TODO(xusheng): use LLIL SSA to do more accurate analysis
# https://github.com/mandiant/capa/issues/1609
reg_names = []
if llil.left.operation == LowLevelILOperation.LLIL_REG:
reg_names.append(llil.left.src.name)
if llil.right.operation == LowLevelILOperation.LLIL_REG:
reg_names.append(llil.right.src.name)
# stack cookie reg should be stack/frame pointer
if not any(reg in ["ebp", "esp", "rbp", "rsp", "sp"] for reg in reg_names):
return False
# expect security cookie init in first basic block within first bytes (instructions)
if len(bb.incoming_edges) == 0 and llil.address < (bb.start + SECURITY_COOKIE_BYTES_DELTA):
return True
# ... or within last bytes (instructions) before a return
if len(bb.outgoing_edges) == 0 and llil.address > (bb.end - SECURITY_COOKIE_BYTES_DELTA):
return True
return False
def extract_insn_nzxor_characteristic_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
parse instruction non-zeroing XOR instruction
ignore expected non-zeroing XORs, e.g. security cookies
"""
func: Function = fh.inner
results = []
def llil_checker(il: LowLevelILInstruction, parent: LowLevelILInstruction, index: int) -> bool:
# If the two operands of the xor instruction are the same, the LLIL will be translated to other instructions,
# e.g., <llil: eax = 0>, (LLIL_SET_REG). So we do not need to check whether the two operands are the same.
if il.operation == LowLevelILOperation.LLIL_XOR:
# Exclude cases related to the stack cookie
if is_nzxor_stack_cookie(fh.inner, bbh.inner[0], il):
return False
results.append((Characteristic("nzxor"), ih.address))
return False
else:
return True
for llil in func.get_llils_at(ih.address):
visit_llil_exprs(llil, llil_checker)
yield from results
def extract_insn_mnemonic_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction mnemonic features"""
insn: DisassemblyInstruction = ih.inner
yield Mnemonic(insn.text[0].text), ih.address
def extract_insn_obfs_call_plus_5_characteristic_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
parse call $+5 instruction from the given instruction.
"""
insn: DisassemblyInstruction = ih.inner
if insn.text[0].text == "call" and insn.text[2].text == "$+5" and insn.length == 5:
yield Characteristic("call $+5"), ih.address
def extract_insn_peb_access_characteristic_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction peb access
fs:[0x30] on x86, gs:[0x60] on x64
"""
func: Function = fh.inner
results = []
def llil_checker(il: LowLevelILInstruction, parent: LowLevelILOperation, index: int) -> bool:
if il.operation != LowLevelILOperation.LLIL_LOAD:
return True
src = il.src
if src.operation != LowLevelILOperation.LLIL_ADD:
return True
left = src.left
right = src.right
if left.operation != LowLevelILOperation.LLIL_REG:
return True
reg = left.src.name
if right.operation != LowLevelILOperation.LLIL_CONST:
return True
value = right.value.value
if (reg, value) not in (("fsbase", 0x30), ("gsbase", 0x60)):
return True
results.append((Characteristic("peb access"), ih.address))
return False
for llil in func.get_llils_at(ih.address):
visit_llil_exprs(llil, llil_checker)
yield from results
def extract_insn_segment_access_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction fs or gs access"""
func: Function = fh.inner
results = []
def llil_checker(il: LowLevelILInstruction, parent: LowLevelILInstruction, index: int) -> bool:
if il.operation == LowLevelILOperation.LLIL_REG:
reg = il.src.name
if reg == "fsbase":
results.append((Characteristic("fs access"), ih.address))
return False
elif reg == "gsbase":
results.append((Characteristic("gs access"), ih.address))
return False
return False
return True
for llil in func.get_llils_at(ih.address):
visit_llil_exprs(llil, llil_checker)
yield from results
def extract_insn_cross_section_cflow(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""inspect the instruction for a CALL or JMP that crosses section boundaries"""
func: Function = fh.inner
bv: BinaryView = func.view
if bv is None:
return
seg1 = bv.get_segment_at(ih.address)
sections1 = bv.get_sections_at(ih.address)
for ref in bv.get_code_refs_from(ih.address):
if len(bv.get_functions_at(ref)) == 0:
continue
seg2 = bv.get_segment_at(ref)
sections2 = bv.get_sections_at(ref)
if seg1 != seg2 or sections1 != sections2:
yield Characteristic("cross section flow"), ih.address
def extract_function_calls_from(fh: FunctionHandle, bbh: 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
"""
func: Function = fh.inner
bv: BinaryView = func.view
if bv is None:
return
for il in func.get_llils_at(ih.address):
if il.operation not in [
LowLevelILOperation.LLIL_CALL,
LowLevelILOperation.LLIL_CALL_STACK_ADJUST,
LowLevelILOperation.LLIL_TAILCALL,
]:
continue
dest = il.dest
if dest.operation == LowLevelILOperation.LLIL_CONST_PTR:
value = dest.value.value
yield Characteristic("calls from"), AbsoluteVirtualAddress(value)
elif dest.operation == LowLevelILOperation.LLIL_CONST:
yield Characteristic("calls from"), AbsoluteVirtualAddress(dest.value)
elif dest.operation == LowLevelILOperation.LLIL_LOAD:
indirect_src = dest.src
if indirect_src.operation == LowLevelILOperation.LLIL_CONST_PTR:
value = indirect_src.value.value
yield Characteristic("calls from"), AbsoluteVirtualAddress(value)
elif indirect_src.operation == LowLevelILOperation.LLIL_CONST:
yield Characteristic("calls from"), AbsoluteVirtualAddress(indirect_src.value)
elif dest.operation == LowLevelILOperation.LLIL_REG:
if dest.value.type in [
RegisterValueType.ImportedAddressValue,
RegisterValueType.ConstantValue,
RegisterValueType.ConstantPointerValue,
]:
yield Characteristic("calls from"), AbsoluteVirtualAddress(dest.value.value)
def extract_function_indirect_call_characteristic_features(
fh: FunctionHandle, bbh: 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
most relevant at the function or basic block scope;
however, its most efficient to extract at the instruction scope
"""
func: Function = fh.inner
llil = func.get_llil_at(ih.address)
if llil is None or llil.operation not in [
LowLevelILOperation.LLIL_CALL,
LowLevelILOperation.LLIL_CALL_STACK_ADJUST,
LowLevelILOperation.LLIL_TAILCALL,
]:
return
if llil.dest.operation in [LowLevelILOperation.LLIL_CONST, LowLevelILOperation.LLIL_CONST_PTR]:
return
if llil.dest.operation == LowLevelILOperation.LLIL_LOAD:
src = llil.dest.src
if src.operation in [LowLevelILOperation.LLIL_CONST, LowLevelILOperation.LLIL_CONST_PTR]:
return
yield Characteristic("indirect call"), ih.address
def extract_features(f: FunctionHandle, bbh: BBHandle, insn: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""extract instruction features"""
for inst_handler in INSTRUCTION_HANDLERS:
for feature, ea in inst_handler(f, bbh, insn):
yield feature, ea
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,
)

View File

@@ -0,0 +1,62 @@
# 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
from typing import Tuple, Iterator
from capa.helpers import assert_never
from capa.features.insn import API, Number
from capa.features.common import String, Feature
from capa.features.address import Address
from capa.features.extractors.cape.models import Call
from capa.features.extractors.base_extractor import CallHandle, ThreadHandle, ProcessHandle
logger = logging.getLogger(__name__)
def extract_call_features(ph: ProcessHandle, th: ThreadHandle, ch: CallHandle) -> Iterator[Tuple[Feature, Address]]:
"""
this method extracts the given call's features (such as API name and arguments),
and returns them as API, Number, and String features.
args:
ph: process handle (for defining the extraction scope)
th: thread handle (for defining the extraction scope)
ch: call handle (for defining the extraction scope)
yields:
Feature, address; where Feature is either: API, Number, or String.
"""
call: Call = ch.inner
# list similar to disassembly: arguments right-to-left, call
for arg in reversed(call.arguments):
value = arg.value
if isinstance(value, list) and len(value) == 0:
# unsure why CAPE captures arguments as empty lists?
continue
elif isinstance(value, str):
yield String(value), ch.address
elif isinstance(value, int):
yield Number(value), ch.address
else:
assert_never(value)
yield API(call.api), ch.address
def extract_features(ph: ProcessHandle, th: ThreadHandle, ch: CallHandle) -> Iterator[Tuple[Feature, Address]]:
for handler in CALL_HANDLERS:
for feature, addr in handler(ph, th, ch):
yield feature, addr
CALL_HANDLERS = (extract_call_features,)

View File

@@ -0,0 +1,145 @@
# 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
from typing import Dict, Tuple, Union, Iterator
import capa.features.extractors.cape.call
import capa.features.extractors.cape.file
import capa.features.extractors.cape.thread
import capa.features.extractors.cape.global_
import capa.features.extractors.cape.process
from capa.exceptions import EmptyReportError, UnsupportedFormatError
from capa.features.common import Feature, Characteristic
from capa.features.address import NO_ADDRESS, Address, AbsoluteVirtualAddress, _NoAddress
from capa.features.extractors.cape.models import Call, Static, Process, CapeReport
from capa.features.extractors.base_extractor import (
CallHandle,
SampleHashes,
ThreadHandle,
ProcessHandle,
DynamicFeatureExtractor,
)
logger = logging.getLogger(__name__)
TESTED_VERSIONS = {"2.2-CAPE", "2.4-CAPE"}
class CapeExtractor(DynamicFeatureExtractor):
def __init__(self, report: CapeReport):
super().__init__(
hashes=SampleHashes(
md5=report.target.file.md5.lower(),
sha1=report.target.file.sha1.lower(),
sha256=report.target.file.sha256.lower(),
)
)
self.report: CapeReport = report
# pre-compute these because we'll yield them at *every* scope.
self.global_features = list(capa.features.extractors.cape.global_.extract_features(self.report))
def get_base_address(self) -> Union[AbsoluteVirtualAddress, _NoAddress, None]:
# value according to the PE header, the actual trace may use a different imagebase
assert self.report.static is not None and self.report.static.pe is not None
return AbsoluteVirtualAddress(self.report.static.pe.imagebase)
def extract_global_features(self) -> Iterator[Tuple[Feature, Address]]:
yield from self.global_features
def extract_file_features(self) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.cape.file.extract_features(self.report)
def get_processes(self) -> Iterator[ProcessHandle]:
yield from capa.features.extractors.cape.file.get_processes(self.report)
def extract_process_features(self, ph: ProcessHandle) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.cape.process.extract_features(ph)
def get_process_name(self, ph) -> str:
process: Process = ph.inner
return process.process_name
def get_threads(self, ph: ProcessHandle) -> Iterator[ThreadHandle]:
yield from capa.features.extractors.cape.process.get_threads(ph)
def extract_thread_features(self, ph: ProcessHandle, th: ThreadHandle) -> Iterator[Tuple[Feature, Address]]:
if False:
# force this routine to be a generator,
# but we don't actually have any elements to generate.
yield Characteristic("never"), NO_ADDRESS
return
def get_calls(self, ph: ProcessHandle, th: ThreadHandle) -> Iterator[CallHandle]:
yield from capa.features.extractors.cape.thread.get_calls(ph, th)
def extract_call_features(
self, ph: ProcessHandle, th: ThreadHandle, ch: CallHandle
) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.cape.call.extract_features(ph, th, ch)
def get_call_name(self, ph, th, ch) -> str:
call: Call = ch.inner
parts = []
parts.append(call.api)
parts.append("(")
for argument in call.arguments:
parts.append(argument.name)
parts.append("=")
if argument.pretty_value:
parts.append(argument.pretty_value)
else:
if isinstance(argument.value, int):
parts.append(hex(argument.value))
elif isinstance(argument.value, str):
parts.append('"')
parts.append(argument.value)
parts.append('"')
elif isinstance(argument.value, list):
pass
else:
capa.helpers.assert_never(argument.value)
parts.append(", ")
if call.arguments:
# remove the trailing comma
parts.pop()
parts.append(")")
parts.append(" -> ")
if call.pretty_return:
parts.append(call.pretty_return)
else:
parts.append(hex(call.return_))
return "".join(parts)
@classmethod
def from_report(cls, report: Dict) -> "CapeExtractor":
cr = CapeReport.model_validate(report)
if cr.info.version not in TESTED_VERSIONS:
logger.warning("CAPE version '%s' not tested/supported yet", cr.info.version)
# observed in 2.4-CAPE reports from capesandbox.com
if cr.static is None and cr.target.file.pe is not None:
cr.static = Static()
cr.static.pe = cr.target.file.pe
if cr.static is None:
raise UnsupportedFormatError("CAPE report missing static analysis")
if cr.static.pe is None:
raise UnsupportedFormatError("CAPE report missing PE analysis")
if len(cr.behavior.processes) == 0:
raise EmptyReportError("CAPE did not capture any processes")
return cls(cr)

View File

@@ -0,0 +1,132 @@
# 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
from typing import Tuple, Iterator
from capa.features.file import Export, Import, Section
from capa.features.common import String, Feature
from capa.features.address import NO_ADDRESS, Address, ProcessAddress, AbsoluteVirtualAddress
from capa.features.extractors.helpers import generate_symbols
from capa.features.extractors.cape.models import CapeReport
from capa.features.extractors.base_extractor import ProcessHandle
logger = logging.getLogger(__name__)
def get_processes(report: CapeReport) -> Iterator[ProcessHandle]:
"""
get all the created processes for a sample
"""
seen_processes = {}
for process in report.behavior.processes:
addr = ProcessAddress(pid=process.process_id, ppid=process.parent_id)
yield ProcessHandle(address=addr, inner=process)
# check for pid and ppid reuse
if addr not in seen_processes:
seen_processes[addr] = [process]
else:
logger.warning(
"pid and ppid reuse detected between process %s and process%s: %s",
process,
"es" if len(seen_processes[addr]) > 1 else "",
seen_processes[addr],
)
seen_processes[addr].append(process)
def extract_import_names(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
"""
extract imported function names
"""
assert report.static is not None and report.static.pe is not None
imports = report.static.pe.imports
if isinstance(imports, dict):
imports = list(imports.values())
assert isinstance(imports, list)
for library in imports:
for function in library.imports:
if not function.name:
continue
for name in generate_symbols(library.dll, function.name, include_dll=True):
yield Import(name), AbsoluteVirtualAddress(function.address)
def extract_export_names(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
assert report.static is not None and report.static.pe is not None
for function in report.static.pe.exports:
yield Export(function.name), AbsoluteVirtualAddress(function.address)
def extract_section_names(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
assert report.static is not None and report.static.pe is not None
for section in report.static.pe.sections:
yield Section(section.name), AbsoluteVirtualAddress(section.virtual_address)
def extract_file_strings(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
if report.strings is not None:
for string in report.strings:
yield String(string), NO_ADDRESS
def extract_used_regkeys(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
for regkey in report.behavior.summary.keys:
yield String(regkey), NO_ADDRESS
def extract_used_files(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
for file in report.behavior.summary.files:
yield String(file), NO_ADDRESS
def extract_used_mutexes(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
for mutex in report.behavior.summary.mutexes:
yield String(mutex), NO_ADDRESS
def extract_used_commands(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
for cmd in report.behavior.summary.executed_commands:
yield String(cmd), NO_ADDRESS
def extract_used_apis(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
for symbol in report.behavior.summary.resolved_apis:
yield String(symbol), NO_ADDRESS
def extract_used_services(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
for svc in report.behavior.summary.created_services:
yield String(svc), NO_ADDRESS
for svc in report.behavior.summary.started_services:
yield String(svc), NO_ADDRESS
def extract_features(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
for handler in FILE_HANDLERS:
for feature, addr in handler(report):
yield feature, addr
FILE_HANDLERS = (
extract_import_names,
extract_export_names,
extract_section_names,
extract_file_strings,
extract_used_regkeys,
extract_used_files,
extract_used_mutexes,
extract_used_commands,
extract_used_apis,
extract_used_services,
)

View File

@@ -0,0 +1,93 @@
# 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
from typing import Tuple, Iterator
from capa.features.common import (
OS,
OS_ANY,
OS_LINUX,
ARCH_I386,
FORMAT_PE,
ARCH_AMD64,
FORMAT_ELF,
OS_WINDOWS,
Arch,
Format,
Feature,
)
from capa.features.address import NO_ADDRESS, Address
from capa.features.extractors.cape.models import CapeReport
logger = logging.getLogger(__name__)
def extract_arch(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
if "Intel 80386" in report.target.file.type:
yield Arch(ARCH_I386), NO_ADDRESS
elif "x86-64" in report.target.file.type:
yield Arch(ARCH_AMD64), NO_ADDRESS
else:
logger.warning("unrecognized Architecture: %s", report.target.file.type)
raise ValueError(
f"unrecognized Architecture from the CAPE report; output of file command: {report.target.file.type}"
)
def extract_format(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
if "PE" in report.target.file.type:
yield Format(FORMAT_PE), NO_ADDRESS
elif "ELF" in report.target.file.type:
yield Format(FORMAT_ELF), NO_ADDRESS
else:
logger.warning("unknown file format, file command output: %s", report.target.file.type)
raise ValueError(
"unrecognized file format from the CAPE report; output of file command: {report.target.file.type}"
)
def extract_os(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
# this variable contains the output of the file command
file_output = report.target.file.type
if "windows" in file_output.lower():
yield OS(OS_WINDOWS), NO_ADDRESS
elif "elf" in file_output.lower():
# operating systems recognized by the file command: https://github.com/file/file/blob/master/src/readelf.c#L609
if "Linux" in file_output:
yield OS(OS_LINUX), NO_ADDRESS
elif "Hurd" in file_output:
yield OS("hurd"), NO_ADDRESS
elif "Solaris" in file_output:
yield OS("solaris"), NO_ADDRESS
elif "kFreeBSD" in file_output:
yield OS("freebsd"), NO_ADDRESS
elif "kNetBSD" in file_output:
yield OS("netbsd"), NO_ADDRESS
else:
# if the operating system information is missing from the cape report, it's likely a bug
logger.warning("unrecognized OS: %s", file_output)
raise ValueError("unrecognized OS from the CAPE report; output of file command: {file_output}")
else:
# the sample is shellcode
logger.debug("unsupported file format, file command output: %s", file_output)
yield OS(OS_ANY), NO_ADDRESS
def extract_features(report: CapeReport) -> Iterator[Tuple[Feature, Address]]:
for global_handler in GLOBAL_HANDLER:
for feature, addr in global_handler(report):
yield feature, addr
GLOBAL_HANDLER = (
extract_format,
extract_os,
extract_arch,
)

View File

@@ -0,0 +1,29 @@
# 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, List
from capa.features.extractors.base_extractor import ProcessHandle
def find_process(processes: List[Dict[str, Any]], ph: ProcessHandle) -> Dict[str, Any]:
"""
find a specific process identified by a process handler.
args:
processes: a list of processes extracted by CAPE
ph: handle of the sought process
return:
a CAPE-defined dictionary for the sought process' information
"""
for process in processes:
if ph.address.ppid == process["parent_id"] and ph.address.pid == process["process_id"]:
return process
return {}

View File

@@ -0,0 +1,446 @@
# 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 binascii
from typing import Any, Dict, List, Union, Literal, Optional
from pydantic import Field, BaseModel, ConfigDict
from typing_extensions import Annotated, TypeAlias
from pydantic.functional_validators import BeforeValidator
def validate_hex_int(value):
if isinstance(value, str):
return int(value, 16) if value.startswith("0x") else int(value, 10)
else:
return value
def validate_hex_bytes(value):
return binascii.unhexlify(value) if isinstance(value, str) else value
HexInt = Annotated[int, BeforeValidator(validate_hex_int)]
HexBytes = Annotated[bytes, BeforeValidator(validate_hex_bytes)]
# a model that *cannot* have extra fields
# if they do, pydantic raises an exception.
# use this for models we rely upon and cannot change.
#
# for things that may be extended and we don't care,
# use FlexibleModel.
class ExactModel(BaseModel):
model_config = ConfigDict(extra="forbid")
# a model that can have extra fields that we ignore.
# use this if we don't want to raise an exception for extra
# data fields that we didn't expect.
class FlexibleModel(BaseModel):
pass
# use this type to indicate that we won't model this data.
# because its not relevant to our use in capa.
#
# while its nice to have full coverage of the data shape,
# it can easily change and break our parsing.
# so we really only want to describe what we'll use.
Skip: TypeAlias = Optional[Any]
# mark fields that we haven't seen yet and need to model.
# pydantic should raise an error when encountering data
# in a field with this type.
# then we can update the model with the discovered shape.
TODO: TypeAlias = None
ListTODO: TypeAlias = List[None]
DictTODO: TypeAlias = ExactModel
EmptyDict: TypeAlias = BaseModel
EmptyList: TypeAlias = List[Any]
class Info(FlexibleModel):
version: str
class ImportedSymbol(ExactModel):
address: HexInt
name: Optional[str] = None
class ImportedDll(ExactModel):
dll: str
imports: List[ImportedSymbol]
class DirectoryEntry(ExactModel):
name: str
virtual_address: HexInt
size: HexInt
class Section(ExactModel):
name: str
raw_address: HexInt
virtual_address: HexInt
virtual_size: HexInt
size_of_data: HexInt
characteristics: str
characteristics_raw: HexInt
entropy: float
class Resource(ExactModel):
name: str
language: Optional[str] = None
sublanguage: str
filetype: Optional[str]
offset: HexInt
size: HexInt
entropy: float
class DigitalSigner(FlexibleModel):
md5_fingerprint: str
not_after: str
not_before: str
serial_number: str
sha1_fingerprint: str
sha256_fingerprint: str
issuer_commonName: Optional[str] = None
issuer_countryName: Optional[str] = None
issuer_localityName: Optional[str] = None
issuer_organizationName: Optional[str] = None
issuer_stateOrProvinceName: Optional[str] = None
subject_commonName: Optional[str] = None
subject_countryName: Optional[str] = None
subject_localityName: Optional[str] = None
subject_organizationName: Optional[str] = None
subject_stateOrProvinceName: Optional[str] = None
extensions_authorityInfoAccess_caIssuers: Optional[str] = None
extensions_authorityKeyIdentifier: Optional[str] = None
extensions_cRLDistributionPoints_0: Optional[str] = None
extensions_certificatePolicies_0: Optional[str] = None
extensions_subjectAltName_0: Optional[str] = None
extensions_subjectKeyIdentifier: Optional[str] = None
class AuxSigner(ExactModel):
name: str
issued_to: str = Field(alias="Issued to")
issued_by: str = Field(alias="Issued by")
expires: str = Field(alias="Expires")
sha1_hash: str = Field(alias="SHA1 hash")
class Signer(ExactModel):
aux_sha1: Optional[str] = None
aux_timestamp: Optional[str] = None
aux_valid: Optional[bool] = None
aux_error: Optional[bool] = None
aux_error_desc: Optional[str] = None
aux_signers: Optional[List[AuxSigner]] = None
class Overlay(ExactModel):
offset: HexInt
size: HexInt
class KV(ExactModel):
name: str
value: str
class ExportedSymbol(ExactModel):
address: HexInt
name: str
ordinal: int
class PE(ExactModel):
peid_signatures: TODO
imagebase: HexInt
entrypoint: HexInt
reported_checksum: HexInt
actual_checksum: HexInt
osversion: str
pdbpath: Optional[str] = None
timestamp: str
# List[ImportedDll], or Dict[basename(dll), ImportedDll]
imports: Union[List[ImportedDll], Dict[str, ImportedDll]]
imported_dll_count: Optional[int] = None
imphash: str
exported_dll_name: Optional[str] = None
exports: List[ExportedSymbol]
dirents: List[DirectoryEntry]
sections: List[Section]
ep_bytes: Optional[HexBytes] = None
overlay: Optional[Overlay] = None
resources: List[Resource]
versioninfo: List[KV]
# base64 encoded data
icon: Optional[str] = None
# MD5-like hash
icon_hash: Optional[str] = None
# MD5-like hash
icon_fuzzy: Optional[str] = None
# short hex string
icon_dhash: Optional[str] = None
digital_signers: List[DigitalSigner]
guest_signers: Signer
# TODO(mr-tz): target.file.dotnet, target.file.extracted_files, target.file.extracted_files_tool,
# target.file.extracted_files_time
# https://github.com/mandiant/capa/issues/1814
class File(FlexibleModel):
type: str
cape_type_code: Optional[int] = None
cape_type: Optional[str] = None
pid: Optional[Union[int, Literal[""]]] = None
name: Union[List[str], str]
path: str
guest_paths: Union[List[str], str, None]
timestamp: Optional[str] = None
#
# hashes
#
crc32: str
md5: str
sha1: str
sha256: str
sha512: str
sha3_384: str
ssdeep: str
# unsure why this would ever be "False"
tlsh: Optional[Union[str, bool]] = None
rh_hash: Optional[str] = None
#
# other metadata, static analysis
#
size: int
pe: Optional[PE] = None
ep_bytes: Optional[HexBytes] = None
entrypoint: Optional[int] = None
data: Optional[str] = None
strings: Optional[List[str]] = None
#
# detections (skip)
#
yara: Skip = None
cape_yara: Skip = None
clamav: Skip = None
virustotal: Skip = None
class ProcessFile(File):
#
# like a File, but also has dynamic analysis results
#
pid: Optional[int] = None
process_path: Optional[str] = None
process_name: Optional[str] = None
module_path: Optional[str] = None
virtual_address: Optional[HexInt] = None
target_pid: Optional[Union[int, str]] = None
target_path: Optional[str] = None
target_process: Optional[str] = None
class Argument(ExactModel):
name: str
# unsure why empty list is provided here
value: Union[HexInt, int, str, EmptyList]
pretty_value: Optional[str] = None
class Call(ExactModel):
timestamp: str
thread_id: int
category: str
api: str
arguments: List[Argument]
status: bool
return_: HexInt = Field(alias="return")
pretty_return: Optional[str] = None
repeated: int
# virtual addresses
caller: HexInt
parentcaller: HexInt
# index into calls array
id: int
class Process(ExactModel):
process_id: int
process_name: str
parent_id: int
module_path: str
first_seen: str
calls: List[Call]
threads: List[int]
environ: Dict[str, str]
class ProcessTree(ExactModel):
name: str
pid: int
parent_id: int
module_path: str
threads: List[int]
environ: Dict[str, str]
children: List["ProcessTree"]
class Summary(ExactModel):
files: List[str]
read_files: List[str]
write_files: List[str]
delete_files: List[str]
keys: List[str]
read_keys: List[str]
write_keys: List[str]
delete_keys: List[str]
executed_commands: List[str]
resolved_apis: List[str]
mutexes: List[str]
created_services: List[str]
started_services: List[str]
class EncryptedBuffer(ExactModel):
process_name: str
pid: int
api_call: str
buffer: str
buffer_size: Optional[int] = None
crypt_key: Optional[Union[HexInt, str]] = None
class Behavior(ExactModel):
summary: Summary
# list of processes, of threads, of calls
processes: List[Process]
# tree of processes
processtree: List[ProcessTree]
anomaly: List[str]
encryptedbuffers: List[EncryptedBuffer]
# these are small objects that describe atomic events,
# like file move, registery access.
# we'll detect the same with our API call analyis.
enhanced: Skip = None
class Target(ExactModel):
category: str
file: File
pe: Optional[PE] = None
class Static(ExactModel):
pe: Optional[PE] = None
flare_capa: Skip = None
class Cape(ExactModel):
payloads: List[ProcessFile]
configs: Skip = None
# flexible because there may be more sorts of analysis
# but we only care about the ones described here.
class CapeReport(FlexibleModel):
# the input file, I think
target: Target
# info about the processing job, like machine and distributed metadata.
info: Info
#
# static analysis results
#
static: Optional[Static] = None
strings: Optional[List[str]] = None
#
# dynamic analysis results
#
# post-processed results: process tree, anomalies, etc
behavior: Behavior
# post-processed results: payloads and extracted configs
CAPE: Optional[Cape] = None
dropped: Optional[List[File]] = None
procdump: Optional[List[ProcessFile]] = None
procmemory: ListTODO
# =========================================================================
# information we won't use in capa
#
#
# NBIs and HBIs
# these are super interesting, but they don't enable use to detect behaviors.
# they take a lot of code to model and details to maintain.
#
# if we come up with a future use for this, go ahead and re-enable!
#
network: Skip = None
suricata: Skip = None
curtain: Skip = None
sysmon: Skip = None
url_analysis: Skip = None
# screenshot hash values
deduplicated_shots: Skip = None
# k-v pairs describing the time it took to run each stage.
statistics: Skip = None
# k-v pairs of ATT&CK ID to signature name or similar.
ttps: Skip = None
# debug log messages
debug: Skip = None
# various signature matches
# we could potentially extend capa to use this info one day,
# though it would be quite sandbox-specific,
# and more detection-oriented than capability detection.
signatures: Skip = None
malfamily_tag: Optional[str] = None
malscore: float
detections: Skip = None
detections2pid: Optional[Dict[int, List[str]]] = None
# AV detections for the sample.
virustotal: Skip = None
@classmethod
def from_buf(cls, buf: bytes) -> "CapeReport":
return cls.model_validate_json(buf)

View File

@@ -0,0 +1,48 @@
# 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
from typing import List, Tuple, Iterator
from capa.features.common import String, Feature
from capa.features.address import Address, ThreadAddress
from capa.features.extractors.cape.models import Process
from capa.features.extractors.base_extractor import ThreadHandle, ProcessHandle
logger = logging.getLogger(__name__)
def get_threads(ph: ProcessHandle) -> Iterator[ThreadHandle]:
"""
get the threads associated with a given process
"""
process: Process = ph.inner
threads: List[int] = process.threads
for thread in threads:
address: ThreadAddress = ThreadAddress(process=ph.address, tid=thread)
yield ThreadHandle(address=address, inner={})
def extract_environ_strings(ph: ProcessHandle) -> Iterator[Tuple[Feature, Address]]:
"""
extract strings from a process' provided environment variables.
"""
process: Process = ph.inner
for value in (value for value in process.environ.values() if value):
yield String(value), ph.address
def extract_features(ph: ProcessHandle) -> Iterator[Tuple[Feature, Address]]:
for handler in PROCESS_HANDLERS:
for feature, addr in handler(ph):
yield feature, addr
PROCESS_HANDLERS = (extract_environ_strings,)

View File

@@ -0,0 +1,32 @@
# 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
from typing import Iterator
from capa.features.address import DynamicCallAddress
from capa.features.extractors.helpers import generate_symbols
from capa.features.extractors.cape.models import Process
from capa.features.extractors.base_extractor import CallHandle, ThreadHandle, ProcessHandle
logger = logging.getLogger(__name__)
def get_calls(ph: ProcessHandle, th: ThreadHandle) -> Iterator[CallHandle]:
process: Process = ph.inner
tid = th.address.tid
for call_index, call in enumerate(process.calls):
if call.thread_id != tid:
continue
for symbol in generate_symbols("", call.api):
call.api = symbol
addr = DynamicCallAddress(thread=th.address, id=call_index)
yield CallHandle(address=addr, inner=call)

View File

@@ -0,0 +1,154 @@
# 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 io
import re
import logging
import binascii
import contextlib
from typing import Tuple, Iterator
import pefile
import capa.features
import capa.features.extractors.elf
import capa.features.extractors.pefile
import capa.features.extractors.strings
from capa.features.common import (
OS,
OS_ANY,
OS_AUTO,
ARCH_ANY,
FORMAT_PE,
FORMAT_DEX,
FORMAT_ELF,
OS_ANDROID,
OS_WINDOWS,
ARCH_DALVIK,
FORMAT_FREEZE,
FORMAT_RESULT,
Arch,
Format,
String,
Feature,
)
from capa.features.freeze import is_freeze
from capa.features.address import NO_ADDRESS, Address, FileOffsetAddress
logger = logging.getLogger(__name__)
# match strings for formats
MATCH_PE = b"MZ"
MATCH_ELF = b"\x7fELF"
MATCH_DEX = b"dex\n"
MATCH_RESULT = b'{"meta":'
MATCH_JSON_OBJECT = b'{"'
def extract_file_strings(buf, **kwargs) -> Iterator[Tuple[String, Address]]:
"""
extract ASCII and UTF-16 LE strings from file
"""
for s in capa.features.extractors.strings.extract_ascii_strings(buf):
yield String(s.s), FileOffsetAddress(s.offset)
for s in capa.features.extractors.strings.extract_unicode_strings(buf):
yield String(s.s), FileOffsetAddress(s.offset)
def extract_format(buf) -> Iterator[Tuple[Feature, Address]]:
if buf.startswith(MATCH_PE):
yield Format(FORMAT_PE), NO_ADDRESS
elif buf.startswith(MATCH_ELF):
yield Format(FORMAT_ELF), NO_ADDRESS
elif len(buf) > 8 and buf.startswith(MATCH_DEX) and buf[7] == 0x00:
yield Format(FORMAT_DEX), NO_ADDRESS
elif is_freeze(buf):
yield Format(FORMAT_FREEZE), NO_ADDRESS
elif buf.startswith(MATCH_RESULT):
yield Format(FORMAT_RESULT), NO_ADDRESS
elif re.sub(rb"\s", b"", buf[:20]).startswith(MATCH_JSON_OBJECT):
# potential start of JSON object data without whitespace
# we don't know what it is exactly, but may support it (e.g. a dynamic CAPE sandbox report)
# skip verdict here and let subsequent code analyze this further
return
else:
# we likely end up here:
# 1. handling a file format (e.g. macho)
#
# for (1), this logic will need to be updated as the format is implemented.
logger.debug("unsupported file format: %s", binascii.hexlify(buf[:4]).decode("ascii"))
return
def extract_arch(buf) -> Iterator[Tuple[Feature, Address]]:
if buf.startswith(MATCH_PE):
yield from capa.features.extractors.pefile.extract_file_arch(pe=pefile.PE(data=buf))
elif buf.startswith(MATCH_RESULT):
yield Arch(ARCH_ANY), NO_ADDRESS
elif buf.startswith(MATCH_ELF):
with contextlib.closing(io.BytesIO(buf)) as f:
arch = capa.features.extractors.elf.detect_elf_arch(f)
if arch not in capa.features.common.VALID_ARCH:
logger.debug("unsupported arch: %s", arch)
return
yield Arch(arch), NO_ADDRESS
elif len(buf) > 8 and buf.startswith(MATCH_DEX) and buf[7] == 0x00:
yield Arch(ARCH_DALVIK), 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 arch,
# but i think this would be rarely used.
# rules that rely on arch 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 Arch", binascii.hexlify(buf[:4]).decode("ascii"))
return
def extract_os(buf, os=OS_AUTO) -> Iterator[Tuple[Feature, Address]]:
if os != OS_AUTO:
yield OS(os), NO_ADDRESS
if buf.startswith(MATCH_PE):
yield OS(OS_WINDOWS), NO_ADDRESS
elif buf.startswith(MATCH_RESULT):
yield OS(OS_ANY), NO_ADDRESS
elif buf.startswith(MATCH_ELF):
with contextlib.closing(io.BytesIO(buf)) as f:
os = capa.features.extractors.elf.detect_elf_os(f)
if os not in capa.features.common.VALID_OS:
logger.debug("unsupported os: %s", os)
return
yield OS(os), NO_ADDRESS
elif len(buf) > 8 and buf.startswith(MATCH_DEX) and buf[7] == 0x00:
yield OS(OS_ANDROID), 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.
# 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", binascii.hexlify(buf[:4]).decode("ascii"))
return

View File

@@ -0,0 +1,421 @@
# 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
import logging
from typing import Set, Dict, List, Tuple, Iterator, Optional, TypedDict
from pathlib import Path
from dataclasses import dataclass
import dexparser.disassembler as disassembler
from dexparser import DEXParser, uleb128_value
from capa.features.file import Import, FunctionName
from capa.features.common import (
OS,
FORMAT_DEX,
OS_ANDROID,
ARCH_DALVIK,
Arch,
Class,
Format,
String,
Feature,
Namespace,
)
from capa.features.address import NO_ADDRESS, Address, DexClassAddress, DexMethodAddress, FileOffsetAddress
from capa.features.extractors.base_extractor import (
BBHandle,
InsnHandle,
SampleHashes,
FunctionHandle,
StaticFeatureExtractor,
)
logger = logging.getLogger(__name__)
# Reference: https://source.android.com/docs/core/runtime/dex-format
class DexProtoId(TypedDict):
shorty_idx: int
return_type_idx: int
param_off: int
class DexMethodId(TypedDict):
class_idx: int
proto_idx: int
name_idx: int
@dataclass
class DexAnalyzedMethod:
class_type: str
name: str
shorty_descriptor: str
return_type: str
parameters: List[str]
id_offset: int = 0
code_offset: int = 0
access_flags: Optional[int] = None
@property
def address(self):
# NOTE: Some methods do not have code, in that case we use the method_id offset
if self.has_code:
return self.code_offset
else:
return self.id_offset
@property
def has_code(self):
# NOTE: code_offset is zero if the method is abstract/native or not defined in a class
return self.code_offset != 0
@property
def has_definition(self):
# NOTE: access_flags is only known if the method is defined in a class
return self.access_flags is not None
@property
def qualified_name(self):
return f"{self.class_type}::{self.name}"
class DexFieldId(TypedDict):
class_idx: int
type_idx: int
name_idx: int
class DexClassDef(TypedDict):
class_idx: int
access_flags: int
superclass_idx: int
interfaces_off: int
source_file_idx: int
annotations_off: int
class_data_off: int
static_values_off: int
class DexFieldDef(TypedDict):
diff: int
access_flags: int
class DexMethodDef(TypedDict):
diff: int
access_flags: int
code_off: int
class DexClassData(TypedDict):
static_fields: List[DexFieldDef]
instance_fields: List[DexFieldDef]
direct_methods: List[DexMethodDef]
virtual_methods: List[DexMethodDef]
@dataclass
class DexAnalyzedClass:
offset: int
class_type: str
superclass_type: str
interfaces: List[str]
source_file: str
data: Optional[DexClassData]
class DexAnnotation(TypedDict):
visibility: int
type_idx_diff: int
size_diff: int
name_idx_diff: int
value_type: int
encoded_value: int
class DexAnalysis:
def get_strings(self):
# NOTE: Copied from dexparser, upstream later
strings: List[Tuple[int, bytes]] = []
string_ids_off = self.dex.header_data["string_ids_off"]
for i in range(self.dex.header_data["string_ids_size"]):
offset = struct.unpack("<L", self.dex.data[string_ids_off + (i * 4) : string_ids_off + (i * 4) + 4])[0]
c_size, size_offset = uleb128_value(self.dex.data, offset)
c_char = self.dex.data[offset + size_offset : offset + size_offset + c_size]
strings.append((offset, c_char))
return strings
def __init__(self, dex: DEXParser):
self.dex = dex
self.strings = self.get_strings()
self.strings_utf8: List[str] = []
for _, data in self.strings:
# NOTE: This is technically incorrect
# Reference: https://source.android.com/devices/tech/dalvik/dex-format#mutf-8
self.strings_utf8.append(data.decode("utf-8", errors="backslashreplace"))
self.type_ids: List[int] = dex.get_typeids()
self.method_ids: List[DexMethodId] = dex.get_methods()
self.proto_ids: List[DexProtoId] = dex.get_protoids()
self.field_ids: List[DexFieldId] = dex.get_fieldids()
self.class_defs: List[DexClassDef] = dex.get_classdef_data()
self._is_analyzing = True
self.used_classes: Set[str] = set()
self.classes = self._analyze_classes()
self.methods = self._analyze_methods()
self.methods_by_address: Dict[int, DexAnalyzedMethod] = {m.address: m for m in self.methods}
self.namespaces: Set[str] = set()
for class_type in self.used_classes:
idx = class_type.rfind(".")
if idx != -1:
self.namespaces.add(class_type[:idx])
for class_type in self.classes:
self.used_classes.remove(class_type)
# Only available after code analysis
self._is_analyzing = False
def analyze_code(self):
# Loop over the classes and analyze them
# self.classes: List[DexClass] = self.dex.get_class_data(offset=-1)
# self.annotations: List[DexAnnotation] = dex.get_annotations(offset=-1)
# self.static_values: List[int] = dex.get_static_values(offset=-1)
pass
def get_string(self, index: int) -> str:
return self.strings_utf8[index]
def _decode_descriptor(self, descriptor: str) -> str:
first = descriptor[0]
if first == "L":
pretty = descriptor[1:-1].replace("/", ".")
if self._is_analyzing:
self.used_classes.add(pretty)
elif first == "[":
pretty = self._decode_descriptor(descriptor[1:]) + "[]"
else:
pretty = disassembler.type_descriptor[first]
return pretty
def get_pretty_type(self, index: int) -> str:
if index == 0xFFFFFFFF:
return "<NO_INDEX>"
descriptor = self.get_string(self.type_ids[index])
return self._decode_descriptor(descriptor)
def _analyze_classes(self):
classes: Dict[str, DexAnalyzedClass] = {}
offset = self.dex.header_data["class_defs_off"]
for index, clazz in enumerate(self.class_defs):
class_type = self.get_pretty_type(clazz["class_idx"])
# Superclass
superclass_idx = clazz["superclass_idx"]
if superclass_idx != 0xFFFFFFFF:
superclass_type = self.get_pretty_type(superclass_idx)
else:
superclass_type = ""
# Interfaces
interfaces = []
interfaces_offset = clazz["interfaces_off"]
if interfaces_offset != 0:
size = struct.unpack("<L", self.dex.data[interfaces_offset : interfaces_offset + 4])[0]
for i in range(size):
type_idx = struct.unpack(
"<H", self.dex.data[interfaces_offset + 4 + i * 2 : interfaces_offset + 6 + i * 2]
)[0]
interface_type = self.get_pretty_type(type_idx)
interfaces.append(interface_type)
# Source file
source_file_idx = clazz["source_file_idx"]
if source_file_idx != 0xFFFFFFFF:
source_file = self.get_string(source_file_idx)
else:
source_file = ""
# Data
data_offset = clazz["class_data_off"]
if data_offset != 0:
data = self.dex.get_class_data(data_offset)
else:
data = None
classes[class_type] = DexAnalyzedClass(
offset=offset + index * 32,
class_type=class_type,
superclass_type=superclass_type,
interfaces=interfaces,
source_file=source_file,
data=data,
)
return classes
def _analyze_methods(self):
methods: List[DexAnalyzedMethod] = []
for method_id in self.method_ids:
proto = self.proto_ids[method_id["proto_idx"]]
parameters = []
param_off = proto["param_off"]
if param_off != 0:
size = struct.unpack("<L", self.dex.data[param_off : param_off + 4])[0]
for i in range(size):
type_idx = struct.unpack("<H", self.dex.data[param_off + 4 + i * 2 : param_off + 6 + i * 2])[0]
param_type = self.get_pretty_type(type_idx)
parameters.append(param_type)
methods.append(
DexAnalyzedMethod(
class_type=self.get_pretty_type(method_id["class_idx"]),
name=self.get_string(method_id["name_idx"]),
shorty_descriptor=self.get_string(proto["shorty_idx"]),
return_type=self.get_pretty_type(proto["return_type_idx"]),
parameters=parameters,
)
)
# Fill in the missing method data
for clazz in self.classes.values():
if clazz.data is None:
continue
for method_def in clazz.data["direct_methods"]:
diff = method_def["diff"]
methods[diff].access_flags = method_def["access_flags"]
methods[diff].code_offset = method_def["code_off"]
for method_def in clazz.data["virtual_methods"]:
diff = method_def["diff"]
methods[diff].access_flags = method_def["access_flags"]
methods[diff].code_offset = method_def["code_off"]
# Fill in the missing code offsets with fake data
offset = self.dex.header_data["method_ids_off"]
for index, method in enumerate(methods):
method.id_offset = offset + index * 8
return methods
def extract_file_features(self) -> Iterator[Tuple[Feature, Address]]:
yield Format(FORMAT_DEX), NO_ADDRESS
for i in range(len(self.strings)):
yield String(self.strings_utf8[i]), FileOffsetAddress(self.strings[i][0])
for method in self.methods:
if method.has_definition:
yield FunctionName(method.qualified_name), DexMethodAddress(method.address)
else:
yield Import(method.qualified_name), DexMethodAddress(method.address)
for namespace in self.namespaces:
yield Namespace(namespace), NO_ADDRESS
for clazz in self.classes.values():
yield Class(clazz.class_type), DexClassAddress(clazz.offset)
for class_type in self.used_classes:
yield Class(class_type), NO_ADDRESS
class DexFeatureExtractor(StaticFeatureExtractor):
def __init__(self, path: Path, *, code_analysis: bool):
super().__init__(hashes=SampleHashes.from_bytes(path.read_bytes()))
self.path: Path = path
self.code_analysis = code_analysis
self.dex = DEXParser(filedir=str(path))
self.analysis = DexAnalysis(self.dex)
# Perform more expensive code analysis only when requested
if self.code_analysis:
self.analysis.analyze_code()
def todo(self):
import inspect
message = "[DexparserFeatureExtractor:TODO] " + inspect.stack()[1].function
logger.debug(message)
def get_base_address(self):
return NO_ADDRESS
def extract_global_features(self) -> Iterator[Tuple[Feature, Address]]:
# These are hardcoded global features
yield Format(FORMAT_DEX), NO_ADDRESS
yield OS(OS_ANDROID), NO_ADDRESS
yield Arch(ARCH_DALVIK), NO_ADDRESS
def extract_file_features(self) -> Iterator[Tuple[Feature, Address]]:
yield from self.analysis.extract_file_features()
def is_library_function(self, addr: Address) -> bool:
assert isinstance(addr, DexMethodAddress)
method = self.analysis.methods_by_address[addr]
# exclude androidx/kotlin stuff?
return not method.has_definition
def get_function_name(self, addr: Address) -> str:
assert isinstance(addr, DexMethodAddress)
method = self.analysis.methods_by_address[addr]
return method.qualified_name
def get_functions(self) -> Iterator[FunctionHandle]:
if not self.code_analysis:
raise Exception("code analysis is disabled")
for method in self.analysis.methods:
yield FunctionHandle(DexMethodAddress(method.address), method)
def extract_function_features(self, f: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
if not self.code_analysis:
raise Exception("code analysis is disabled")
method: DexAnalyzedMethod = f.inner
if method.has_code:
return self.todo()
yield
def get_basic_blocks(self, f: FunctionHandle) -> Iterator[BBHandle]:
if not self.code_analysis:
raise Exception("code analysis is disabled")
method: DexAnalyzedMethod = f.inner
if method.has_code:
return self.todo()
yield
def extract_basic_block_features(self, f: FunctionHandle, bb: BBHandle) -> Iterator[Tuple[Feature, Address]]:
if not self.code_analysis:
raise Exception("code analysis is disabled")
return self.todo()
yield
def get_instructions(self, f: FunctionHandle, bb: BBHandle) -> Iterator[InsnHandle]:
if not self.code_analysis:
raise Exception("code analysis is disabled")
return self.todo()
yield
def extract_insn_features(
self, f: FunctionHandle, bb: BBHandle, insn: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
if not self.code_analysis:
raise Exception("code analysis is disabled")
return self.todo()
yield

View File

@@ -0,0 +1,161 @@
# 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 __future__ import annotations
from typing import Dict, List, Tuple, Union, Iterator, Optional
from pathlib import Path
import dnfile
from dncil.cil.opcode import OpCodes
import capa.features.extractors
import capa.features.extractors.dotnetfile
import capa.features.extractors.dnfile.file
import capa.features.extractors.dnfile.insn
import capa.features.extractors.dnfile.function
from capa.features.common import Feature
from capa.features.address import NO_ADDRESS, Address, DNTokenAddress, DNTokenOffsetAddress
from capa.features.extractors.dnfile.types import DnType, DnUnmanagedMethod
from capa.features.extractors.base_extractor import (
BBHandle,
InsnHandle,
SampleHashes,
FunctionHandle,
StaticFeatureExtractor,
)
from capa.features.extractors.dnfile.helpers import (
get_dotnet_types,
get_dotnet_fields,
get_dotnet_managed_imports,
get_dotnet_managed_methods,
get_dotnet_unmanaged_imports,
get_dotnet_managed_method_bodies,
)
class DnFileFeatureExtractorCache:
def __init__(self, pe: dnfile.dnPE):
self.imports: Dict[int, Union[DnType, DnUnmanagedMethod]] = {}
self.native_imports: Dict[int, Union[DnType, DnUnmanagedMethod]] = {}
self.methods: Dict[int, Union[DnType, DnUnmanagedMethod]] = {}
self.fields: Dict[int, Union[DnType, DnUnmanagedMethod]] = {}
self.types: Dict[int, Union[DnType, DnUnmanagedMethod]] = {}
for import_ in get_dotnet_managed_imports(pe):
self.imports[import_.token] = import_
for native_import in get_dotnet_unmanaged_imports(pe):
self.native_imports[native_import.token] = native_import
for method in get_dotnet_managed_methods(pe):
self.methods[method.token] = method
for field in get_dotnet_fields(pe):
self.fields[field.token] = field
for type_ in get_dotnet_types(pe):
self.types[type_.token] = type_
def get_import(self, token: int) -> Optional[Union[DnType, DnUnmanagedMethod]]:
return self.imports.get(token)
def get_native_import(self, token: int) -> Optional[Union[DnType, DnUnmanagedMethod]]:
return self.native_imports.get(token)
def get_method(self, token: int) -> Optional[Union[DnType, DnUnmanagedMethod]]:
return self.methods.get(token)
def get_field(self, token: int) -> Optional[Union[DnType, DnUnmanagedMethod]]:
return self.fields.get(token)
def get_type(self, token: int) -> Optional[Union[DnType, DnUnmanagedMethod]]:
return self.types.get(token)
class DnfileFeatureExtractor(StaticFeatureExtractor):
def __init__(self, path: Path):
self.pe: dnfile.dnPE = dnfile.dnPE(str(path))
super().__init__(hashes=SampleHashes.from_bytes(path.read_bytes()))
# pre-compute .NET token lookup tables; each .NET method has access to this cache for feature extraction
# most relevant at instruction scope
self.token_cache: DnFileFeatureExtractorCache = DnFileFeatureExtractorCache(self.pe)
# pre-compute these because we'll yield them at *every* scope.
self.global_features: List[Tuple[Feature, Address]] = []
self.global_features.extend(capa.features.extractors.dotnetfile.extract_file_format())
self.global_features.extend(capa.features.extractors.dotnetfile.extract_file_os(pe=self.pe))
self.global_features.extend(capa.features.extractors.dotnetfile.extract_file_arch(pe=self.pe))
def get_base_address(self):
return NO_ADDRESS
def extract_global_features(self):
yield from self.global_features
def extract_file_features(self):
yield from capa.features.extractors.dnfile.file.extract_features(self.pe)
def get_functions(self) -> Iterator[FunctionHandle]:
# create a method lookup table
methods: Dict[Address, FunctionHandle] = {}
for token, method in get_dotnet_managed_method_bodies(self.pe):
fh: FunctionHandle = FunctionHandle(
address=DNTokenAddress(token),
inner=method,
ctx={"pe": self.pe, "calls_from": set(), "calls_to": set(), "cache": self.token_cache},
)
# method tokens should be unique
assert fh.address not in methods.keys()
methods[fh.address] = fh
# calculate unique calls to/from each method
for fh in methods.values():
for insn in fh.inner.instructions:
if insn.opcode not in (
OpCodes.Call,
OpCodes.Callvirt,
OpCodes.Jmp,
OpCodes.Newobj,
):
continue
address: DNTokenAddress = DNTokenAddress(insn.operand.value)
# record call to destination method; note: we only consider MethodDef methods for destinations
dest: Optional[FunctionHandle] = methods.get(address)
if dest is not None:
dest.ctx["calls_to"].add(fh.address)
# record call from source method; note: we record all unique calls from a MethodDef method, not just
# those calls to other MethodDef methods e.g. calls to imported MemberRef methods
fh.ctx["calls_from"].add(address)
yield from methods.values()
def extract_function_features(self, fh) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.dnfile.function.extract_features(fh)
def get_basic_blocks(self, f) -> Iterator[BBHandle]:
# each dotnet method is considered 1 basic block
yield BBHandle(
address=f.address,
inner=f.inner,
)
def extract_basic_block_features(self, fh, bbh):
# we don't support basic block features
yield from []
def get_instructions(self, fh, bbh):
for insn in bbh.inner.instructions:
yield InsnHandle(
address=DNTokenOffsetAddress(bbh.address, insn.offset - (fh.inner.offset + fh.inner.header_size)),
inner=insn,
)
def extract_insn_features(self, fh, bbh, ih) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.dnfile.insn.extract_features(fh, bbh, ih)

View File

@@ -0,0 +1,63 @@
# 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 __future__ import annotations
from typing import Tuple, Iterator
import dnfile
import capa.features.extractors.dotnetfile
from capa.features.file import Import, FunctionName
from capa.features.common import Class, Format, String, Feature, Namespace, Characteristic
from capa.features.address import Address
def extract_file_import_names(pe: dnfile.dnPE) -> Iterator[Tuple[Import, Address]]:
yield from capa.features.extractors.dotnetfile.extract_file_import_names(pe=pe)
def extract_file_format(pe: dnfile.dnPE) -> Iterator[Tuple[Format, Address]]:
yield from capa.features.extractors.dotnetfile.extract_file_format(pe=pe)
def extract_file_function_names(pe: dnfile.dnPE) -> Iterator[Tuple[FunctionName, Address]]:
yield from capa.features.extractors.dotnetfile.extract_file_function_names(pe=pe)
def extract_file_strings(pe: dnfile.dnPE) -> Iterator[Tuple[String, Address]]:
yield from capa.features.extractors.dotnetfile.extract_file_strings(pe=pe)
def extract_file_mixed_mode_characteristic_features(pe: dnfile.dnPE) -> Iterator[Tuple[Characteristic, Address]]:
yield from capa.features.extractors.dotnetfile.extract_file_mixed_mode_characteristic_features(pe=pe)
def extract_file_namespace_features(pe: dnfile.dnPE) -> Iterator[Tuple[Namespace, Address]]:
yield from capa.features.extractors.dotnetfile.extract_file_namespace_features(pe=pe)
def extract_file_class_features(pe: dnfile.dnPE) -> Iterator[Tuple[Class, Address]]:
yield from capa.features.extractors.dotnetfile.extract_file_class_features(pe=pe)
def extract_features(pe: dnfile.dnPE) -> Iterator[Tuple[Feature, Address]]:
for file_handler in FILE_HANDLERS:
for feature, address in file_handler(pe):
yield feature, address
FILE_HANDLERS = (
extract_file_import_names,
extract_file_function_names,
extract_file_strings,
extract_file_format,
extract_file_mixed_mode_characteristic_features,
extract_file_namespace_features,
extract_file_class_features,
)

View File

@@ -0,0 +1,50 @@
# 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 __future__ import annotations
import logging
from typing import Tuple, Iterator
from capa.features.common import Feature, Characteristic
from capa.features.address import Address
from capa.features.extractors.base_extractor import FunctionHandle
logger = logging.getLogger(__name__)
def extract_function_calls_to(fh: FunctionHandle) -> Iterator[Tuple[Characteristic, Address]]:
"""extract callers to a function"""
for dest in fh.ctx["calls_to"]:
yield Characteristic("calls to"), dest
def extract_function_calls_from(fh: FunctionHandle) -> Iterator[Tuple[Characteristic, Address]]:
"""extract callers from a function"""
for src in fh.ctx["calls_from"]:
yield Characteristic("calls from"), src
def extract_recursive_call(fh: FunctionHandle) -> Iterator[Tuple[Characteristic, Address]]:
"""extract recursive function call"""
if fh.address in fh.ctx["calls_to"]:
yield Characteristic("recursive call"), fh.address
def extract_function_loop(fh: FunctionHandle) -> Iterator[Tuple[Characteristic, Address]]:
"""extract loop indicators from a function"""
raise NotImplementedError()
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
FUNCTION_HANDLERS = (extract_function_calls_to, extract_function_calls_from, extract_recursive_call)

View File

@@ -0,0 +1,335 @@
# 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 __future__ import annotations
import logging
from typing import Dict, Tuple, Union, Iterator, Optional
import dnfile
from dncil.cil.body import CilMethodBody
from dncil.cil.error import MethodBodyFormatError
from dncil.clr.token import Token, StringToken, InvalidToken
from dncil.cil.body.reader import CilMethodBodyReaderBase
from capa.features.common import FeatureAccess
from capa.features.extractors.dnfile.types import DnType, DnUnmanagedMethod
logger = logging.getLogger(__name__)
class DnfileMethodBodyReader(CilMethodBodyReaderBase):
def __init__(self, pe: dnfile.dnPE, row: dnfile.mdtable.MethodDefRow):
self.pe: dnfile.dnPE = pe
self.offset: int = self.pe.get_offset_from_rva(row.Rva)
def read(self, n: int) -> bytes:
data: bytes = self.pe.get_data(self.pe.get_rva_from_offset(self.offset), n)
self.offset += n
return data
def tell(self) -> int:
return self.offset
def seek(self, offset: int) -> int:
self.offset = offset
return self.offset
def resolve_dotnet_token(pe: dnfile.dnPE, token: Token) -> Union[dnfile.base.MDTableRow, InvalidToken, str]:
"""map generic token to string or table row"""
assert pe.net is not None
assert pe.net.mdtables is not None
if isinstance(token, StringToken):
user_string: Optional[str] = read_dotnet_user_string(pe, token)
if user_string is None:
return InvalidToken(token.value)
return user_string
table: Optional[dnfile.base.ClrMetaDataTable] = pe.net.mdtables.tables.get(token.table)
if table is None:
# table index is not valid
return InvalidToken(token.value)
try:
return table.rows[token.rid - 1]
except IndexError:
# table index is valid but row index is not valid
return InvalidToken(token.value)
def read_dotnet_method_body(pe: dnfile.dnPE, row: dnfile.mdtable.MethodDefRow) -> Optional[CilMethodBody]:
"""read dotnet method body"""
try:
return CilMethodBody(DnfileMethodBodyReader(pe, row))
except MethodBodyFormatError as e:
logger.debug("failed to parse managed method body @ 0x%08x (%s)", row.Rva, e)
return None
def read_dotnet_user_string(pe: dnfile.dnPE, token: StringToken) -> Optional[str]:
"""read user string from #US stream"""
assert pe.net is not None
if pe.net.user_strings is None:
# stream may not exist (seen in obfuscated .NET)
logger.debug("#US stream does not exist for stream index 0x%08x", token.rid)
return None
try:
user_string: Optional[dnfile.stream.UserString] = pe.net.user_strings.get_us(token.rid)
except UnicodeDecodeError as e:
logger.debug("failed to decode #US stream index 0x%08x (%s)", token.rid, e)
return None
if user_string is None:
return None
return user_string.value
def get_dotnet_managed_imports(pe: dnfile.dnPE) -> Iterator[DnType]:
"""get managed imports from MemberRef table
see https://www.ntcore.com/files/dotnetformat.htm
10 - MemberRef Table
Each row represents an imported method
Class (index into the TypeRef, ModuleRef, MethodDef, TypeSpec or TypeDef tables)
Name (index into String heap)
01 - TypeRef Table
Each row represents an imported class, its namespace and the assembly which contains it
TypeName (index into String heap)
TypeNamespace (index into String heap)
"""
for rid, member_ref in iter_dotnet_table(pe, dnfile.mdtable.MemberRef.number):
assert isinstance(member_ref, dnfile.mdtable.MemberRefRow)
if not isinstance(member_ref.Class.row, dnfile.mdtable.TypeRefRow):
# only process class imports from TypeRef table
continue
token: int = calculate_dotnet_token_value(dnfile.mdtable.MemberRef.number, rid)
access: Optional[str]
# assume .NET imports starting with get_/set_ are used to access a property
if member_ref.Name.startswith("get_"):
access = FeatureAccess.READ
elif member_ref.Name.startswith("set_"):
access = FeatureAccess.WRITE
else:
access = None
member_ref_name: str = member_ref.Name
if member_ref_name.startswith(("get_", "set_")):
# remove get_/set_ from MemberRef name
member_ref_name = member_ref_name[4:]
yield DnType(
token,
member_ref.Class.row.TypeName,
namespace=member_ref.Class.row.TypeNamespace,
member=member_ref_name,
access=access,
)
def get_dotnet_methoddef_property_accessors(pe: dnfile.dnPE) -> Iterator[Tuple[int, str]]:
"""get MethodDef methods used to access properties
see https://www.ntcore.com/files/dotnetformat.htm
24 - MethodSemantics Table
Links Events and Properties to specific methods. For example one Event can be associated to more methods. A property uses this table to associate get/set methods.
Semantics (a 2-byte bitmask of type MethodSemanticsAttributes)
Method (index into the MethodDef table)
Association (index into the Event or Property table; more precisely, a HasSemantics coded index)
"""
for rid, method_semantics in iter_dotnet_table(pe, dnfile.mdtable.MethodSemantics.number):
assert isinstance(method_semantics, dnfile.mdtable.MethodSemanticsRow)
if method_semantics.Association.row is None:
logger.debug("MethodSemantics[0x%X] Association row is None", rid)
continue
if isinstance(method_semantics.Association.row, dnfile.mdtable.EventRow):
# ignore events
logger.debug("MethodSemantics[0x%X] ignoring Event", rid)
continue
if method_semantics.Method.table is None:
logger.debug("MethodSemantics[0x%X] Method table is None", rid)
continue
token: int = calculate_dotnet_token_value(
method_semantics.Method.table.number, method_semantics.Method.row_index
)
if method_semantics.Semantics.msSetter:
yield token, FeatureAccess.WRITE
elif method_semantics.Semantics.msGetter:
yield token, FeatureAccess.READ
def get_dotnet_managed_methods(pe: dnfile.dnPE) -> Iterator[DnType]:
"""get managed method names from TypeDef table
see https://www.ntcore.com/files/dotnetformat.htm
02 - TypeDef Table
Each row represents a class in the current assembly.
TypeName (index into String heap)
TypeNamespace (index into String heap)
MethodList (index into MethodDef table; it marks the first of a contiguous run of Methods owned by this Type)
"""
accessor_map: Dict[int, str] = {}
for methoddef, methoddef_access in get_dotnet_methoddef_property_accessors(pe):
accessor_map[methoddef] = methoddef_access
for rid, typedef in iter_dotnet_table(pe, dnfile.mdtable.TypeDef.number):
assert isinstance(typedef, dnfile.mdtable.TypeDefRow)
for idx, method in enumerate(typedef.MethodList):
if method.table is None:
logger.debug("TypeDef[0x%X] MethodList[0x%X] table is None", rid, idx)
continue
if method.row is None:
logger.debug("TypeDef[0x%X] MethodList[0x%X] row is None", rid, idx)
continue
token: int = calculate_dotnet_token_value(method.table.number, method.row_index)
access: Optional[str] = accessor_map.get(token)
method_name: str = method.row.Name
if method_name.startswith(("get_", "set_")):
# remove get_/set_
method_name = method_name[4:]
yield DnType(token, typedef.TypeName, namespace=typedef.TypeNamespace, member=method_name, access=access)
def get_dotnet_fields(pe: dnfile.dnPE) -> Iterator[DnType]:
"""get fields from TypeDef table
see https://www.ntcore.com/files/dotnetformat.htm
02 - TypeDef Table
Each row represents a class in the current assembly.
TypeName (index into String heap)
TypeNamespace (index into String heap)
FieldList (index into Field table; it marks the first of a contiguous run of Fields owned by this Type)
"""
for rid, typedef in iter_dotnet_table(pe, dnfile.mdtable.TypeDef.number):
assert isinstance(typedef, dnfile.mdtable.TypeDefRow)
for idx, field in enumerate(typedef.FieldList):
if field.table is None:
logger.debug("TypeDef[0x%X] FieldList[0x%X] table is None", rid, idx)
continue
if field.row is None:
logger.debug("TypeDef[0x%X] FieldList[0x%X] row is None", rid, idx)
continue
token: int = calculate_dotnet_token_value(field.table.number, field.row_index)
yield DnType(token, typedef.TypeName, namespace=typedef.TypeNamespace, member=field.row.Name)
def get_dotnet_managed_method_bodies(pe: dnfile.dnPE) -> Iterator[Tuple[int, CilMethodBody]]:
"""get managed methods from MethodDef table"""
for rid, method_def in iter_dotnet_table(pe, dnfile.mdtable.MethodDef.number):
assert isinstance(method_def, dnfile.mdtable.MethodDefRow)
if not method_def.ImplFlags.miIL or any((method_def.Flags.mdAbstract, method_def.Flags.mdPinvokeImpl)):
# skip methods that do not have a method body
continue
body: Optional[CilMethodBody] = read_dotnet_method_body(pe, method_def)
if body is None:
logger.debug("MethodDef[0x%X] method body is None", rid)
continue
token: int = calculate_dotnet_token_value(dnfile.mdtable.MethodDef.number, rid)
yield token, body
def get_dotnet_unmanaged_imports(pe: dnfile.dnPE) -> Iterator[DnUnmanagedMethod]:
"""get unmanaged imports from ImplMap table
see https://www.ntcore.com/files/dotnetformat.htm
28 - ImplMap Table
ImplMap table holds information about unmanaged methods that can be reached from managed code, using PInvoke dispatch
MemberForwarded (index into the Field or MethodDef table; more precisely, a MemberForwarded coded index)
ImportName (index into the String heap)
ImportScope (index into the ModuleRef table)
"""
for rid, impl_map in iter_dotnet_table(pe, dnfile.mdtable.ImplMap.number):
assert isinstance(impl_map, dnfile.mdtable.ImplMapRow)
module: str
if impl_map.ImportScope.row is None:
logger.debug("ImplMap[0x%X] ImportScope row is None", rid)
module = ""
else:
module = impl_map.ImportScope.row.Name
method: str = impl_map.ImportName
member_forward_table: int
if impl_map.MemberForwarded.table is None:
logger.debug("ImplMap[0x%X] MemberForwarded table is None", rid)
continue
else:
member_forward_table = impl_map.MemberForwarded.table.number
member_forward_row: int = impl_map.MemberForwarded.row_index
# ECMA says "Each row of the ImplMap table associates a row in the MethodDef table (MemberForwarded) with the
# name of a routine (ImportName) in some unmanaged DLL (ImportScope)"; so we calculate and map the MemberForwarded
# MethodDef table token to help us later record native import method calls made from CIL
token: int = calculate_dotnet_token_value(member_forward_table, member_forward_row)
# like Kernel32.dll
if module and "." in module:
module = module.split(".")[0]
# like kernel32.CreateFileA
yield DnUnmanagedMethod(token, module, method)
def get_dotnet_types(pe: dnfile.dnPE) -> Iterator[DnType]:
"""get .NET types from TypeDef and TypeRef tables"""
for rid, typedef in iter_dotnet_table(pe, dnfile.mdtable.TypeDef.number):
assert isinstance(typedef, dnfile.mdtable.TypeDefRow)
typedef_token: int = calculate_dotnet_token_value(dnfile.mdtable.TypeDef.number, rid)
yield DnType(typedef_token, typedef.TypeName, namespace=typedef.TypeNamespace)
for rid, typeref in iter_dotnet_table(pe, dnfile.mdtable.TypeRef.number):
assert isinstance(typeref, dnfile.mdtable.TypeRefRow)
typeref_token: int = calculate_dotnet_token_value(dnfile.mdtable.TypeRef.number, rid)
yield DnType(typeref_token, typeref.TypeName, namespace=typeref.TypeNamespace)
def calculate_dotnet_token_value(table: int, rid: int) -> int:
return ((table & 0xFF) << Token.TABLE_SHIFT) | (rid & Token.RID_MASK)
def is_dotnet_mixed_mode(pe: dnfile.dnPE) -> bool:
assert pe.net is not None
assert pe.net.Flags is not None
return not bool(pe.net.Flags.CLR_ILONLY)
def iter_dotnet_table(pe: dnfile.dnPE, table_index: int) -> Iterator[Tuple[int, dnfile.base.MDTableRow]]:
assert pe.net is not None
assert pe.net.mdtables is not None
for rid, row in enumerate(pe.net.mdtables.tables.get(table_index, [])):
# .NET tables are 1-indexed
yield rid + 1, row

View File

@@ -0,0 +1,227 @@
# 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 __future__ import annotations
import logging
from typing import TYPE_CHECKING, Tuple, Union, Iterator, Optional
if TYPE_CHECKING:
from capa.features.extractors.dnfile.extractor import DnFileFeatureExtractorCache
import dnfile
from dncil.clr.token import Token, StringToken, InvalidToken
from dncil.cil.opcode import OpCodes
import capa.features.extractors.helpers
from capa.features.insn import API, Number, Property
from capa.features.common import Class, String, Feature, Namespace, FeatureAccess, Characteristic
from capa.features.address import Address
from capa.features.extractors.dnfile.types import DnType, DnUnmanagedMethod
from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle
from capa.features.extractors.dnfile.helpers import (
resolve_dotnet_token,
read_dotnet_user_string,
calculate_dotnet_token_value,
)
logger = logging.getLogger(__name__)
def get_callee(
pe: dnfile.dnPE, cache: DnFileFeatureExtractorCache, token: Token
) -> Optional[Union[DnType, DnUnmanagedMethod]]:
"""map .NET token to un/managed (generic) method"""
token_: int
if token.table == dnfile.mdtable.MethodSpec.number:
# map MethodSpec to MethodDef or MemberRef
row: Union[dnfile.base.MDTableRow, InvalidToken, str] = resolve_dotnet_token(pe, token)
assert isinstance(row, dnfile.mdtable.MethodSpecRow)
if row.Method.table is None:
logger.debug("MethodSpec[0x%X] Method table is None", token.rid)
return None
token_ = calculate_dotnet_token_value(row.Method.table.number, row.Method.row_index)
else:
token_ = token.value
callee: Optional[Union[DnType, DnUnmanagedMethod]] = cache.get_import(token_)
if callee is None:
# we must check unmanaged imports before managed methods because we map forwarded managed methods
# to their unmanaged imports; we prefer a forwarded managed method be mapped to its unmanaged import for analysis
callee = cache.get_native_import(token_)
if callee is None:
callee = cache.get_method(token_)
return callee
def extract_insn_api_features(fh: FunctionHandle, bh, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction API features"""
if ih.inner.opcode not in (
OpCodes.Call,
OpCodes.Callvirt,
OpCodes.Jmp,
OpCodes.Newobj,
):
return
callee: Optional[Union[DnType, DnUnmanagedMethod]] = get_callee(fh.ctx["pe"], fh.ctx["cache"], ih.inner.operand)
if isinstance(callee, DnType):
# ignore methods used to access properties
if callee.access is None:
# like System.IO.File::Delete
yield API(str(callee)), ih.address
elif isinstance(callee, DnUnmanagedMethod):
# like kernel32.CreateFileA
for name in capa.features.extractors.helpers.generate_symbols(callee.module, callee.method):
yield API(name), ih.address
def extract_insn_property_features(fh: FunctionHandle, bh, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction property features"""
name: Optional[str] = None
access: Optional[str] = None
if ih.inner.opcode in (OpCodes.Call, OpCodes.Callvirt, OpCodes.Jmp):
# property access via MethodDef or MemberRef
callee: Optional[Union[DnType, DnUnmanagedMethod]] = get_callee(fh.ctx["pe"], fh.ctx["cache"], ih.inner.operand)
if isinstance(callee, DnType):
if callee.access is not None:
name = str(callee)
access = callee.access
elif ih.inner.opcode in (OpCodes.Ldfld, OpCodes.Ldflda, OpCodes.Ldsfld, OpCodes.Ldsflda):
# property read via Field
read_field: Optional[Union[DnType, DnUnmanagedMethod]] = fh.ctx["cache"].get_field(ih.inner.operand.value)
if read_field is not None:
name = str(read_field)
access = FeatureAccess.READ
elif ih.inner.opcode in (OpCodes.Stfld, OpCodes.Stsfld):
# property write via Field
write_field: Optional[Union[DnType, DnUnmanagedMethod]] = fh.ctx["cache"].get_field(ih.inner.operand.value)
if write_field is not None:
name = str(write_field)
access = FeatureAccess.WRITE
if name is not None:
if access is not None:
yield Property(name, access=access), ih.address
yield Property(name), ih.address
def extract_insn_namespace_class_features(
fh: FunctionHandle, bh, ih: InsnHandle
) -> Iterator[Tuple[Union[Namespace, Class], Address]]:
"""parse instruction namespace and class features"""
type_: Optional[Union[DnType, DnUnmanagedMethod]] = None
if ih.inner.opcode in (
OpCodes.Call,
OpCodes.Callvirt,
OpCodes.Jmp,
OpCodes.Ldvirtftn,
OpCodes.Ldftn,
OpCodes.Newobj,
):
# method call - includes managed methods (MethodDef, TypeRef) and properties (MethodSemantics, TypeRef)
type_ = get_callee(fh.ctx["pe"], fh.ctx["cache"], ih.inner.operand)
elif ih.inner.opcode in (
OpCodes.Ldfld,
OpCodes.Ldflda,
OpCodes.Ldsfld,
OpCodes.Ldsflda,
OpCodes.Stfld,
OpCodes.Stsfld,
):
# field access
type_ = fh.ctx["cache"].get_field(ih.inner.operand.value)
# ECMA 335 VI.C.4.10
elif ih.inner.opcode in (
OpCodes.Initobj,
OpCodes.Box,
OpCodes.Castclass,
OpCodes.Cpobj,
OpCodes.Isinst,
OpCodes.Ldelem,
OpCodes.Ldelema,
OpCodes.Ldobj,
OpCodes.Mkrefany,
OpCodes.Newarr,
OpCodes.Refanyval,
OpCodes.Sizeof,
OpCodes.Stobj,
OpCodes.Unbox,
OpCodes.Constrained,
OpCodes.Stelem,
OpCodes.Unbox_Any,
):
# type access
type_ = fh.ctx["cache"].get_type(ih.inner.operand.value)
if isinstance(type_, DnType):
yield Class(DnType.format_name(type_.class_, namespace=type_.namespace)), ih.address
if type_.namespace:
yield Namespace(type_.namespace), ih.address
def extract_insn_number_features(fh, bh, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction number features"""
if ih.inner.is_ldc():
yield Number(ih.inner.get_ldc()), ih.address
def extract_insn_string_features(fh: FunctionHandle, bh, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction string features"""
if not ih.inner.is_ldstr():
return
if not isinstance(ih.inner.operand, StringToken):
return
user_string: Optional[str] = read_dotnet_user_string(fh.ctx["pe"], ih.inner.operand)
if user_string is None:
return
if len(user_string) >= 4:
yield String(user_string), ih.address
def extract_unmanaged_call_characteristic_features(
fh: FunctionHandle, bb: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Characteristic, Address]]:
if ih.inner.opcode not in (OpCodes.Call, OpCodes.Callvirt, OpCodes.Jmp):
return
row: Union[str, InvalidToken, dnfile.base.MDTableRow] = resolve_dotnet_token(fh.ctx["pe"], ih.inner.operand)
if not isinstance(row, dnfile.mdtable.MethodDefRow):
return
if any((row.Flags.mdPinvokeImpl, row.ImplFlags.miUnmanaged, row.ImplFlags.miNative)):
yield Characteristic("unmanaged call"), ih.address
def extract_features(fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""extract instruction features"""
for inst_handler in INSTRUCTION_HANDLERS:
for feature, addr in inst_handler(fh, bbh, ih):
assert isinstance(addr, Address)
yield feature, addr
INSTRUCTION_HANDLERS = (
extract_insn_api_features,
extract_insn_property_features,
extract_insn_number_features,
extract_insn_string_features,
extract_insn_namespace_class_features,
extract_unmanaged_call_characteristic_features,
)

View File

@@ -0,0 +1,74 @@
# 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 Optional
class DnType:
def __init__(self, token: int, class_: str, namespace: str = "", member: str = "", access: Optional[str] = None):
self.token: int = token
self.access: Optional[str] = access
self.namespace: str = namespace
self.class_: str = class_
if member == ".ctor":
member = "ctor"
if member == ".cctor":
member = "cctor"
self.member: str = member
def __hash__(self):
return hash((self.token, self.access, self.namespace, self.class_, self.member))
def __eq__(self, other):
return (
self.token == other.token
and self.access == other.access
and self.namespace == other.namespace
and self.class_ == other.class_
and self.member == other.member
)
def __str__(self):
return DnType.format_name(self.class_, namespace=self.namespace, member=self.member)
def __repr__(self):
return str(self)
@staticmethod
def format_name(class_: str, namespace: str = "", member: str = ""):
# like File::OpenRead
name: str = f"{class_}::{member}" if member else class_
if namespace:
# like System.IO.File::OpenRead
name = f"{namespace}.{name}"
return name
class DnUnmanagedMethod:
def __init__(self, token: int, module: str, method: str):
self.token: int = token
self.module: str = module
self.method: str = method
def __hash__(self):
return hash((self.token, self.module, self.method))
def __eq__(self, other):
return self.token == other.token and self.module == other.module and self.method == other.method
def __str__(self):
return DnUnmanagedMethod.format_name(self.module, self.method)
def __repr__(self):
return str(self)
@staticmethod
def format_name(module, method):
return f"{module}.{method}"

View File

@@ -0,0 +1,239 @@
# 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
from typing import Tuple, Iterator
from pathlib import Path
import dnfile
import pefile
import capa.features.extractors.helpers
from capa.features.file import Import, FunctionName
from capa.features.common import (
OS,
OS_ANY,
ARCH_ANY,
ARCH_I386,
FORMAT_PE,
ARCH_AMD64,
FORMAT_DOTNET,
Arch,
Class,
Format,
String,
Feature,
Namespace,
Characteristic,
)
from capa.features.address import NO_ADDRESS, Address, DNTokenAddress
from capa.features.extractors.dnfile.types import DnType
from capa.features.extractors.base_extractor import SampleHashes, StaticFeatureExtractor
from capa.features.extractors.dnfile.helpers import (
iter_dotnet_table,
is_dotnet_mixed_mode,
get_dotnet_managed_imports,
get_dotnet_managed_methods,
calculate_dotnet_token_value,
get_dotnet_unmanaged_imports,
)
logger = logging.getLogger(__name__)
def extract_file_format(**kwargs) -> Iterator[Tuple[Format, Address]]:
yield Format(FORMAT_PE), NO_ADDRESS
yield Format(FORMAT_DOTNET), NO_ADDRESS
def extract_file_import_names(pe: dnfile.dnPE, **kwargs) -> Iterator[Tuple[Import, Address]]:
for method in get_dotnet_managed_imports(pe):
# like System.IO.File::OpenRead
yield Import(str(method)), DNTokenAddress(method.token)
for imp in get_dotnet_unmanaged_imports(pe):
# like kernel32.CreateFileA
for name in capa.features.extractors.helpers.generate_symbols(imp.module, imp.method, include_dll=True):
yield Import(name), DNTokenAddress(imp.token)
def extract_file_function_names(pe: dnfile.dnPE, **kwargs) -> Iterator[Tuple[FunctionName, Address]]:
for method in get_dotnet_managed_methods(pe):
yield FunctionName(str(method)), DNTokenAddress(method.token)
def extract_file_namespace_features(pe: dnfile.dnPE, **kwargs) -> Iterator[Tuple[Namespace, Address]]:
"""emit namespace features from TypeRef and TypeDef tables"""
# namespaces may be referenced multiple times, so we need to filter
namespaces = set()
for _, typedef in iter_dotnet_table(pe, dnfile.mdtable.TypeDef.number):
# emit internal .NET namespaces
assert isinstance(typedef, dnfile.mdtable.TypeDefRow)
namespaces.add(typedef.TypeNamespace)
for _, typeref in iter_dotnet_table(pe, dnfile.mdtable.TypeRef.number):
# emit external .NET namespaces
assert isinstance(typeref, dnfile.mdtable.TypeRefRow)
namespaces.add(typeref.TypeNamespace)
# namespaces may be empty, discard
namespaces.discard("")
for namespace in namespaces:
# namespace do not have an associated token, so we yield 0x0
yield Namespace(namespace), NO_ADDRESS
def extract_file_class_features(pe: dnfile.dnPE, **kwargs) -> Iterator[Tuple[Class, Address]]:
"""emit class features from TypeRef and TypeDef tables"""
for rid, typedef in iter_dotnet_table(pe, dnfile.mdtable.TypeDef.number):
# emit internal .NET classes
assert isinstance(typedef, dnfile.mdtable.TypeDefRow)
token = calculate_dotnet_token_value(dnfile.mdtable.TypeDef.number, rid)
yield Class(DnType.format_name(typedef.TypeName, namespace=typedef.TypeNamespace)), DNTokenAddress(token)
for rid, typeref in iter_dotnet_table(pe, dnfile.mdtable.TypeRef.number):
# emit external .NET classes
assert isinstance(typeref, dnfile.mdtable.TypeRefRow)
token = calculate_dotnet_token_value(dnfile.mdtable.TypeRef.number, rid)
yield Class(DnType.format_name(typeref.TypeName, namespace=typeref.TypeNamespace)), DNTokenAddress(token)
def extract_file_os(**kwargs) -> Iterator[Tuple[OS, Address]]:
yield OS(OS_ANY), NO_ADDRESS
def extract_file_arch(pe: dnfile.dnPE, **kwargs) -> Iterator[Tuple[Arch, Address]]:
# to distinguish in more detail, see https://stackoverflow.com/a/23614024/10548020
# .NET 4.5 added option: any CPU, 32-bit preferred
assert pe.net is not None
assert pe.net.Flags is not None
if pe.net.Flags.CLR_32BITREQUIRED and pe.PE_TYPE == pefile.OPTIONAL_HEADER_MAGIC_PE:
yield Arch(ARCH_I386), NO_ADDRESS
elif not pe.net.Flags.CLR_32BITREQUIRED and pe.PE_TYPE == pefile.OPTIONAL_HEADER_MAGIC_PE_PLUS:
yield Arch(ARCH_AMD64), NO_ADDRESS
else:
yield Arch(ARCH_ANY), NO_ADDRESS
def extract_file_strings(pe: dnfile.dnPE, **kwargs) -> Iterator[Tuple[String, Address]]:
yield from capa.features.extractors.common.extract_file_strings(pe.__data__)
def extract_file_mixed_mode_characteristic_features(
pe: dnfile.dnPE, **kwargs
) -> Iterator[Tuple[Characteristic, Address]]:
if is_dotnet_mixed_mode(pe):
yield Characteristic("mixed mode"), NO_ADDRESS
def extract_file_features(pe: dnfile.dnPE) -> Iterator[Tuple[Feature, Address]]:
for file_handler in FILE_HANDLERS:
for feature, addr in file_handler(pe=pe): # type: ignore
yield feature, addr
FILE_HANDLERS = (
extract_file_import_names,
extract_file_function_names,
extract_file_strings,
extract_file_format,
extract_file_mixed_mode_characteristic_features,
extract_file_namespace_features,
extract_file_class_features,
)
def extract_global_features(pe: dnfile.dnPE) -> Iterator[Tuple[Feature, Address]]:
for handler in GLOBAL_HANDLERS:
for feature, va in handler(pe=pe): # type: ignore
yield feature, va
GLOBAL_HANDLERS = (
extract_file_os,
extract_file_arch,
)
class DotnetFileFeatureExtractor(StaticFeatureExtractor):
def __init__(self, path: Path):
super().__init__(hashes=SampleHashes.from_bytes(path.read_bytes()))
self.path: Path = path
self.pe: dnfile.dnPE = dnfile.dnPE(str(path))
def get_base_address(self):
return NO_ADDRESS
def get_entry_point(self) -> int:
# self.pe.net.Flags.CLT_NATIVE_ENTRYPOINT
# True: native EP: Token
# False: managed EP: RVA
assert self.pe.net is not None
assert self.pe.net.struct is not None
return self.pe.net.struct.EntryPointTokenOrRva
def extract_global_features(self):
yield from extract_global_features(self.pe)
def extract_file_features(self):
yield from extract_file_features(self.pe)
def is_dotnet_file(self) -> bool:
return bool(self.pe.net)
def is_mixed_mode(self) -> bool:
return is_dotnet_mixed_mode(self.pe)
def get_runtime_version(self) -> Tuple[int, int]:
assert self.pe.net is not None
assert self.pe.net.struct is not None
assert self.pe.net.struct.MajorRuntimeVersion is not None
assert self.pe.net.struct.MinorRuntimeVersion is not None
return self.pe.net.struct.MajorRuntimeVersion, self.pe.net.struct.MinorRuntimeVersion
def get_meta_version_string(self) -> str:
assert self.pe.net is not None
assert self.pe.net.metadata is not None
assert self.pe.net.metadata.struct is not None
assert self.pe.net.metadata.struct.Version is not None
vbuf = self.pe.net.metadata.struct.Version
assert isinstance(vbuf, bytes)
return vbuf.rstrip(b"\x00").decode("utf-8")
def get_functions(self):
raise NotImplementedError("DotnetFileFeatureExtractor can only be used to extract file features")
def extract_function_features(self, f):
raise NotImplementedError("DotnetFileFeatureExtractor can only be used to extract file features")
def get_basic_blocks(self, f):
raise NotImplementedError("DotnetFileFeatureExtractor can only be used to extract file features")
def extract_basic_block_features(self, f, bb):
raise NotImplementedError("DotnetFileFeatureExtractor can only be used to extract file features")
def get_instructions(self, f, bb):
raise NotImplementedError("DotnetFileFeatureExtractor can only be used to extract file features")
def extract_insn_features(self, f, bb, insn):
raise NotImplementedError("DotnetFileFeatureExtractor can only be used to extract file features")
def is_library_function(self, va):
raise NotImplementedError("DotnetFileFeatureExtractor can only be used to extract file features")
def get_function_name(self, va):
raise NotImplementedError("DotnetFileFeatureExtractor can only be used to extract file features")

View File

@@ -0,0 +1,985 @@
# 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
import logging
import itertools
import collections
from enum import Enum
from typing import Set, Dict, List, Tuple, BinaryIO, Iterator, Optional
from dataclasses import dataclass
import Elf # from vivisect
logger = logging.getLogger(__name__)
def align(v, alignment):
remainder = v % alignment
if remainder == 0:
return v
else:
return v + (alignment - remainder)
def read_cstr(buf, offset) -> str:
s = buf[offset:]
s, _, _ = s.partition(b"\x00")
return s.decode("utf-8")
class CorruptElfFile(ValueError):
pass
class OS(str, Enum):
HPUX = "hpux"
NETBSD = "netbsd"
LINUX = "linux"
HURD = "hurd"
_86OPEN = "86open"
SOLARIS = "solaris"
AIX = "aix"
IRIX = "irix"
FREEBSD = "freebsd"
TRU64 = "tru64"
MODESTO = "modesto"
OPENBSD = "openbsd"
OPENVMS = "openvms"
NSK = "nsk"
AROS = "aros"
FENIXOS = "fenixos"
CLOUD = "cloud"
SYLLABLE = "syllable"
NACL = "nacl"
ANDROID = "android"
# via readelf: https://github.com/bminor/binutils-gdb/blob/c0e94211e1ac05049a4ce7c192c9d14d1764eb3e/binutils/readelf.c#L19635-L19658
# and here: https://github.com/bminor/binutils-gdb/blob/34c54daa337da9fadf87d2706d6a590ae1f88f4d/include/elf/common.h#L933-L939
GNU_ABI_TAG = {
0: OS.LINUX,
1: OS.HURD,
2: OS.SOLARIS,
3: OS.FREEBSD,
4: OS.NETBSD,
5: OS.SYLLABLE,
6: OS.NACL,
}
@dataclass
class Phdr:
type: int
offset: int
vaddr: int
paddr: int
filesz: int
buf: bytes
@dataclass
class Shdr:
name: int
type: int
flags: int
addr: int
offset: int
size: int
link: int
entsize: int
buf: bytes
@classmethod
def from_viv(cls, section, buf: bytes) -> "Shdr":
return cls(
section.sh_name,
section.sh_type,
section.sh_flags,
section.sh_addr,
section.sh_offset,
section.sh_size,
section.sh_link,
section.sh_entsize,
buf,
)
class ELF:
def __init__(self, f: BinaryIO):
self.f = f
# these will all be initialized in `_parse()`
self.bitness: int
self.endian: str
self.e_phentsize: int
self.e_phnum: int
self.e_shentsize: int
self.e_shnum: int
self.phbuf: bytes
self.shbuf: bytes
self._parse()
def _parse(self):
self.f.seek(0x0)
self.file_header = self.f.read(0x40)
if not self.file_header.startswith(b"\x7fELF"):
raise CorruptElfFile("missing magic header")
ei_class, ei_data = struct.unpack_from("BB", self.file_header, 4)
logger.debug("ei_class: 0x%02x ei_data: 0x%02x", ei_class, ei_data)
if ei_class == 1:
self.bitness = 32
elif ei_class == 2:
self.bitness = 64
else:
raise CorruptElfFile(f"invalid ei_class: 0x{ei_class:02x}")
if ei_data == 1:
self.endian = "<"
elif ei_data == 2:
self.endian = ">"
else:
raise CorruptElfFile(f"not an ELF file: invalid ei_data: 0x{ei_data:02x}")
if self.bitness == 32:
e_phoff, e_shoff = struct.unpack_from(self.endian + "II", self.file_header, 0x1C)
self.e_phentsize, self.e_phnum = struct.unpack_from(self.endian + "HH", self.file_header, 0x2A)
self.e_shentsize, self.e_shnum = struct.unpack_from(self.endian + "HH", self.file_header, 0x2E)
elif self.bitness == 64:
e_phoff, e_shoff = struct.unpack_from(self.endian + "QQ", self.file_header, 0x20)
self.e_phentsize, self.e_phnum = struct.unpack_from(self.endian + "HH", self.file_header, 0x36)
self.e_shentsize, self.e_shnum = struct.unpack_from(self.endian + "HH", self.file_header, 0x3A)
else:
raise NotImplementedError()
logger.debug("e_phoff: 0x%02x e_phentsize: 0x%02x e_phnum: %d", e_phoff, self.e_phentsize, self.e_phnum)
self.f.seek(e_phoff)
program_header_size = self.e_phnum * self.e_phentsize
self.phbuf = self.f.read(program_header_size)
if len(self.phbuf) != program_header_size:
logger.warning("failed to read program headers")
self.e_phnum = 0
self.f.seek(e_shoff)
section_header_size = self.e_shnum * self.e_shentsize
self.shbuf = self.f.read(section_header_size)
if len(self.shbuf) != section_header_size:
logger.warning("failed to read section headers")
self.e_shnum = 0
OSABI = {
# via pyelftools: https://github.com/eliben/pyelftools/blob/0664de05ed2db3d39041e2d51d19622a8ef4fb0f/elftools/elf/enums.py#L35-L58
# some candidates are commented out because the are not useful values,
# at least when guessing OSes
# 0: "SYSV", # too often used when OS is not SYSV
1: OS.HPUX,
2: OS.NETBSD,
3: OS.LINUX,
4: OS.HURD,
5: OS._86OPEN,
6: OS.SOLARIS,
7: OS.AIX,
8: OS.IRIX,
9: OS.FREEBSD,
10: OS.TRU64,
11: OS.MODESTO,
12: OS.OPENBSD,
13: OS.OPENVMS,
14: OS.NSK,
15: OS.AROS,
16: OS.FENIXOS,
17: OS.CLOUD,
# 53: "SORTFIX", # i can't find any reference to this OS, i dont think it exists
# 64: "ARM_AEABI", # not an OS
# 97: "ARM", # not an OS
# 255: "STANDALONE", # not an OS
}
@property
def ei_osabi(self) -> Optional[OS]:
(ei_osabi,) = struct.unpack_from(self.endian + "B", self.file_header, 7)
return ELF.OSABI.get(ei_osabi)
MACHINE = {
# via https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html
1: "M32",
2: "SPARC",
3: "i386",
4: "68K",
5: "88K",
6: "486",
7: "860",
8: "MIPS",
9: "S370",
10: "MIPS_RS3_LE",
11: "RS6000",
15: "PA_RISC",
16: "nCUBE",
17: "VPP500",
18: "SPARC32PLUS",
19: "960",
20: "PPC",
21: "PPC64",
22: "S390",
23: "SPU",
36: "V800",
37: "FR20",
38: "RH32",
39: "RCE",
40: "ARM",
41: "ALPHA",
42: "SH",
43: "SPARCV9",
44: "TRICORE",
45: "ARC",
46: "H8_300",
47: "H8_300H",
48: "H8S",
49: "H8_500",
50: "IA_64",
51: "MIPS_X",
52: "COLDFIRE",
53: "68HC12",
54: "MMA",
55: "PCP",
56: "NCPU",
57: "NDR1",
58: "STARCORE",
59: "ME16",
60: "ST100",
61: "TINYJ",
62: "amd64",
63: "PDSP",
64: "PDP10",
65: "PDP11",
66: "FX66",
67: "ST9PLUS",
68: "ST7",
69: "68HC16",
70: "68HC11",
71: "68HC08",
72: "68HC05",
73: "SVX",
74: "ST19",
75: "VAX",
76: "CRIS",
77: "JAVELIN",
78: "FIREPATH",
79: "ZSP",
80: "MMIX",
81: "HUANY",
82: "PRISM",
83: "AVR",
84: "FR30",
85: "D10V",
86: "D30V",
87: "V850",
88: "M32R",
89: "MN10300",
90: "MN10200",
91: "PJ",
92: "OPENRISC",
93: "ARC_A5",
94: "XTENSA",
95: "VIDEOCORE",
96: "TMM_GPP",
97: "NS32K",
98: "TPC",
99: "SNP1K",
100: "ST200",
}
@property
def e_machine(self) -> Optional[str]:
(e_machine,) = struct.unpack_from(self.endian + "H", self.file_header, 0x12)
return ELF.MACHINE.get(e_machine)
def parse_program_header(self, i) -> Phdr:
phent_offset = i * self.e_phentsize
phent = self.phbuf[phent_offset : phent_offset + self.e_phentsize]
(p_type,) = struct.unpack_from(self.endian + "I", phent, 0x0)
logger.debug("ph:p_type: 0x%04x", p_type)
if self.bitness == 32:
p_offset, p_vaddr, p_paddr, p_filesz = struct.unpack_from(self.endian + "IIII", phent, 0x4)
elif self.bitness == 64:
p_offset, p_vaddr, p_paddr, p_filesz = struct.unpack_from(self.endian + "QQQQ", phent, 0x8)
else:
raise NotImplementedError()
logger.debug("ph:p_offset: 0x%02x p_filesz: 0x%04x", p_offset, p_filesz)
self.f.seek(p_offset)
buf = self.f.read(p_filesz)
if len(buf) != p_filesz:
raise ValueError("failed to read program header content")
return Phdr(p_type, p_offset, p_vaddr, p_paddr, p_filesz, buf)
@property
def program_headers(self):
for i in range(self.e_phnum):
try:
yield self.parse_program_header(i)
except ValueError:
continue
def parse_section_header(self, i) -> Shdr:
shent_offset = i * self.e_shentsize
shent = self.shbuf[shent_offset : shent_offset + self.e_shentsize]
if self.bitness == 32:
sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, _, _, sh_entsize = struct.unpack_from(
self.endian + "IIIIIIIIII", shent, 0x0
)
elif self.bitness == 64:
sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, _, _, sh_entsize = struct.unpack_from(
self.endian + "IIQQQQIIQQ", shent, 0x0
)
else:
raise NotImplementedError()
logger.debug("sh:sh_offset: 0x%02x sh_size: 0x%04x", sh_offset, sh_size)
self.f.seek(sh_offset)
buf = self.f.read(sh_size)
if len(buf) != sh_size:
raise ValueError("failed to read section header content")
return Shdr(sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_entsize, buf)
@property
def section_headers(self):
for i in range(self.e_shnum):
try:
yield self.parse_section_header(i)
except ValueError:
continue
@property
def linker(self):
PT_INTERP = 0x3
for phdr in self.program_headers:
if phdr.type != PT_INTERP:
continue
return read_cstr(phdr.buf, 0)
@property
def versions_needed(self) -> Dict[str, Set[str]]:
# symbol version requirements are stored in the .gnu.version_r section,
# which has type SHT_GNU_verneed (0x6ffffffe).
#
# this contains a linked list of ElfXX_Verneed structs,
# each referencing a linked list of ElfXX_Vernaux structs.
# strings are stored in the section referenced by the sh_link field of the section header.
# each Verneed struct contains a reference to the name of the library,
# each Vernaux struct contains a reference to the name of a symbol.
SHT_GNU_VERNEED = 0x6FFFFFFE
for shdr in self.section_headers:
if shdr.type != SHT_GNU_VERNEED:
continue
# the linked section contains strings referenced by the verneed structures.
linked_shdr = self.parse_section_header(shdr.link)
versions_needed = collections.defaultdict(set)
# read verneed structures from the start of the section
# until the vn_next link is 0x0.
# each entry describes a shared object that is required by this binary.
vn_offset = 0x0
while True:
# ElfXX_Verneed layout is the same on 32 and 64 bit
vn_version, vn_cnt, vn_file, vn_aux, vn_next = struct.unpack_from(
self.endian + "HHIII", shdr.buf, vn_offset
)
if vn_version != 1:
# unexpected format, don't try to keep parsing
break
# shared object names, like: "libdl.so.2"
so_name = read_cstr(linked_shdr.buf, vn_file)
# read vernaux structures linked from the verneed structure.
# there should be vn_cnt of these.
# each entry describes an ABI name required by the shared object.
vna_offset = vn_offset + vn_aux
for _ in range(vn_cnt):
# ElfXX_Vernaux layout is the same on 32 and 64 bit
_, _, _, vna_name, vna_next = struct.unpack_from(self.endian + "IHHII", shdr.buf, vna_offset)
# ABI names, like: "GLIBC_2.2.5"
abi = read_cstr(linked_shdr.buf, vna_name)
versions_needed[so_name].add(abi)
vna_offset += vna_next
vn_offset += vn_next
if vn_next == 0:
break
return dict(versions_needed)
return {}
@property
def dynamic_entries(self) -> Iterator[Tuple[int, int]]:
"""
read the entries from the dynamic section,
yielding the tag and value for each entry.
"""
DT_NULL = 0x0
PT_DYNAMIC = 0x2
for phdr in self.program_headers:
if phdr.type != PT_DYNAMIC:
continue
offset = 0x0
while True:
if self.bitness == 32:
d_tag, d_val = struct.unpack_from(self.endian + "II", phdr.buf, offset)
offset += 8
elif self.bitness == 64:
d_tag, d_val = struct.unpack_from(self.endian + "QQ", phdr.buf, offset)
offset += 16
else:
raise NotImplementedError()
if d_tag == DT_NULL:
break
yield d_tag, d_val
@property
def strtab(self) -> Optional[bytes]:
"""
fetch the bytes of the string table
referenced by the dynamic section.
"""
DT_STRTAB = 0x5
DT_STRSZ = 0xA
strtab_addr = None
strtab_size = None
for d_tag, d_val in self.dynamic_entries:
if d_tag == DT_STRTAB:
strtab_addr = d_val
break
for d_tag, d_val in self.dynamic_entries:
if d_tag == DT_STRSZ:
strtab_size = d_val
break
if strtab_addr is None:
return None
if strtab_size is None:
return None
strtab_offset = None
for shdr in self.section_headers:
# the section header address should be defined
if shdr.addr and shdr.addr <= strtab_addr < shdr.addr + shdr.size:
strtab_offset = shdr.offset + (strtab_addr - shdr.addr)
break
if strtab_offset is None:
return None
self.f.seek(strtab_offset)
strtab_buf = self.f.read(strtab_size)
if len(strtab_buf) != strtab_size:
return None
return strtab_buf
@property
def needed(self) -> Iterator[str]:
"""
read the names of DT_NEEDED entries from the dynamic section,
which correspond to dependencies on other shared objects,
like: `libpthread.so.0`
"""
DT_NEEDED = 0x1
strtab = self.strtab
if not strtab:
return
for d_tag, d_val in self.dynamic_entries:
if d_tag != DT_NEEDED:
continue
try:
yield read_cstr(strtab, d_val)
except UnicodeDecodeError as e:
logger.warning("failed to read DT_NEEDED entry: %s", str(e))
@property
def symtab(self) -> Optional[Tuple[Shdr, Shdr]]:
"""
fetch the Shdr for the symtab and the associated strtab.
"""
SHT_SYMTAB = 0x2
for shdr in self.section_headers:
if shdr.type != SHT_SYMTAB:
continue
# the linked section contains strings referenced by the symtab structures.
strtab_shdr = self.parse_section_header(shdr.link)
return shdr, strtab_shdr
return None
@dataclass
class ABITag:
os: OS
kmajor: int
kminor: int
kpatch: int
class PHNote:
def __init__(self, endian: str, buf: bytes):
self.endian = endian
self.buf = buf
# these will be initialized in `_parse()`
self.type_: int
self.descsz: int
self.name: str
self._parse()
def _parse(self):
namesz, self.descsz, self.type_ = struct.unpack_from(self.endian + "III", self.buf, 0x0)
name_offset = 0xC
self.desc_offset = name_offset + align(namesz, 0x4)
logger.debug("ph:namesz: 0x%02x descsz: 0x%02x type: 0x%04x", namesz, self.descsz, self.type_)
self.name = self.buf[name_offset : name_offset + namesz].partition(b"\x00")[0].decode("ascii")
logger.debug("name: %s", self.name)
@property
def abi_tag(self) -> Optional[ABITag]:
if self.type_ != 1:
# > The type field shall be 1.
# Linux Standard Base Specification 1.2
# ref: https://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html
return None
if self.name != "GNU":
return None
if self.descsz < 16:
return None
desc = self.buf[self.desc_offset : self.desc_offset + self.descsz]
abi_tag, kmajor, kminor, kpatch = struct.unpack_from(self.endian + "IIII", desc, 0x0)
logger.debug("GNU_ABI_TAG: 0x%02x", abi_tag)
os = GNU_ABI_TAG.get(abi_tag)
if not os:
return None
logger.debug("abi tag: %s earliest compatible kernel: %d.%d.%d", os, kmajor, kminor, kpatch)
return ABITag(os, kmajor, kminor, kpatch)
class SHNote:
def __init__(self, endian: str, buf: bytes):
self.endian = endian
self.buf = buf
# these will be initialized in `_parse()`
self.type_: int
self.descsz: int
self.name: str
self._parse()
def _parse(self):
namesz, self.descsz, self.type_ = struct.unpack_from(self.endian + "III", self.buf, 0x0)
name_offset = 0xC
self.desc_offset = name_offset + align(namesz, 0x4)
logger.debug("sh:namesz: 0x%02x descsz: 0x%02x type: 0x%04x", namesz, self.descsz, self.type_)
name_buf = self.buf[name_offset : name_offset + namesz]
self.name = read_cstr(name_buf, 0x0)
logger.debug("sh:name: %s", self.name)
@property
def abi_tag(self) -> Optional[ABITag]:
if self.name != "GNU":
return None
if self.descsz < 16:
return None
desc = self.buf[self.desc_offset : self.desc_offset + self.descsz]
abi_tag, kmajor, kminor, kpatch = struct.unpack_from(self.endian + "IIII", desc, 0x0)
logger.debug("GNU_ABI_TAG: 0x%02x", abi_tag)
os = GNU_ABI_TAG.get(abi_tag)
if not os:
return None
logger.debug("abi tag: %s earliest compatible kernel: %d.%d.%d", os, kmajor, kminor, kpatch)
return ABITag(os, kmajor, kminor, kpatch)
@dataclass
class Symbol:
name_offset: int
value: int
size: int
info: int
other: int
shndx: int
class SymTab:
def __init__(
self,
endian: str,
bitness: int,
symtab: Shdr,
strtab: Shdr,
) -> None:
self.symbols: List[Symbol] = []
self.symtab = symtab
self.strtab = strtab
self._parse(endian, bitness, symtab.buf)
def _parse(self, endian: str, bitness: int, symtab_buf: bytes) -> None:
"""
return the symbol's information in
the order specified by sys/elf32.h
"""
if self.symtab.entsize == 0:
return
for i in range(int(len(self.symtab.buf) / self.symtab.entsize)):
if bitness == 32:
name_offset, value, size, info, other, shndx = struct.unpack_from(
endian + "IIIBBH", symtab_buf, i * self.symtab.entsize
)
elif bitness == 64:
name_offset, info, other, shndx, value, size = struct.unpack_from(
endian + "IBBHQQ", symtab_buf, i * self.symtab.entsize
)
self.symbols.append(Symbol(name_offset, value, size, info, other, shndx))
def get_name(self, symbol: Symbol) -> str:
"""
fetch a symbol's name from symtab's
associated strings' section (SHT_STRTAB)
"""
if not self.strtab:
raise ValueError("no strings found")
for i in range(symbol.name_offset, self.strtab.size):
if self.strtab.buf[i] == 0:
return self.strtab.buf[symbol.name_offset : i].decode("utf-8")
raise ValueError("symbol name not found")
def get_symbols(self) -> Iterator[Symbol]:
"""
return a tuple: (name, value, size, info, other, shndx)
for each symbol contained in the symbol table
"""
yield from self.symbols
@classmethod
def from_viv(cls, elf: Elf.Elf) -> Optional["SymTab"]:
endian = "<" if elf.getEndian() == 0 else ">"
bitness = elf.bits
SHT_SYMTAB = 0x2
for section in elf.sections:
if section.sh_type == SHT_SYMTAB:
strtab_section = elf.sections[section.sh_link]
sh_symtab = Shdr.from_viv(section, elf.readAtOffset(section.sh_offset, section.sh_size))
sh_strtab = Shdr.from_viv(
strtab_section, elf.readAtOffset(strtab_section.sh_offset, strtab_section.sh_size)
)
try:
return cls(endian, bitness, sh_symtab, sh_strtab)
except NameError:
return None
except Exception:
# all exceptions that could be encountered by
# cls._parse() imply a faulty symbol's table.
raise CorruptElfFile("malformed symbol's table")
def guess_os_from_osabi(elf: ELF) -> Optional[OS]:
return elf.ei_osabi
def guess_os_from_ph_notes(elf: ELF) -> Optional[OS]:
# search for PT_NOTE sections that specify an OS
# for example, on Linux there is a GNU section with minimum kernel version
PT_NOTE = 0x4
for phdr in elf.program_headers:
if phdr.type != PT_NOTE:
continue
note = PHNote(elf.endian, phdr.buf)
if note.type_ != 1:
# > The type field shall be 1.
# Linux Standard Base Specification 1.2
# ref: https://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html
continue
if note.name == "Linux":
logger.debug("note owner: %s", "LINUX")
return OS.LINUX
elif note.name == "OpenBSD":
logger.debug("note owner: %s", "OPENBSD")
return OS.OPENBSD
elif note.name == "NetBSD":
logger.debug("note owner: %s", "NETBSD")
return OS.NETBSD
elif note.name == "FreeBSD":
logger.debug("note owner: %s", "FREEBSD")
return OS.FREEBSD
elif note.name == "Android":
logger.debug("note owner: %s", "Android")
# see the following for parsing the structure:
# https://android.googlesource.com/platform/ndk/+/master/parse_elfnote.py
return OS.ANDROID
elif note.name == "GNU":
abi_tag = note.abi_tag
if abi_tag:
return abi_tag.os
else:
# cannot make a guess about the OS, but probably linux or hurd
pass
return None
def guess_os_from_sh_notes(elf: ELF) -> Optional[OS]:
# search for notes stored in sections that aren't visible in program headers.
# e.g. .note.Linux in Linux kernel modules.
SHT_NOTE = 0x7
for shdr in elf.section_headers:
if shdr.type != SHT_NOTE:
continue
note = SHNote(elf.endian, shdr.buf)
if note.name == "Linux":
logger.debug("note owner: %s", "LINUX")
return OS.LINUX
elif note.name == "OpenBSD":
logger.debug("note owner: %s", "OPENBSD")
return OS.OPENBSD
elif note.name == "NetBSD":
logger.debug("note owner: %s", "NETBSD")
return OS.NETBSD
elif note.name == "FreeBSD":
logger.debug("note owner: %s", "FREEBSD")
return OS.FREEBSD
elif note.name == "GNU":
abi_tag = note.abi_tag
if abi_tag:
return abi_tag.os
else:
# cannot make a guess about the OS, but probably linux or hurd
pass
return None
def guess_os_from_linker(elf: ELF) -> Optional[OS]:
# search for recognizable dynamic linkers (interpreters)
# for example, on linux, we see file paths like: /lib64/ld-linux-x86-64.so.2
linker = elf.linker
if linker and "ld-linux" in elf.linker:
return OS.LINUX
return None
def guess_os_from_abi_versions_needed(elf: ELF) -> Optional[OS]:
# then lets look for GLIBC symbol versioning requirements.
# this will let us guess about linux/hurd in some cases.
versions_needed = elf.versions_needed
if any(abi.startswith("GLIBC") for abi in itertools.chain(*versions_needed.values())):
# there are any GLIBC versions needed
if elf.e_machine != "i386":
# GLIBC runs on Linux and Hurd.
# for Hurd, its *only* on i386.
# so if we're not on i386, then we're on Linux.
return OS.LINUX
else:
# we're on i386, so we could be on either Linux or Hurd.
linker = elf.linker
if linker and "ld-linux" in linker:
return OS.LINUX
elif linker and "/ld.so" in linker:
return OS.HURD
else:
# we don't have any good guesses based on versions needed
pass
return None
def guess_os_from_needed_dependencies(elf: ELF) -> Optional[OS]:
for needed in elf.needed:
if needed.startswith("libmachuser.so"):
return OS.HURD
if needed.startswith("libhurduser.so"):
return OS.HURD
if needed.startswith("libandroid.so"):
return OS.ANDROID
return None
def guess_os_from_symtab(elf: ELF) -> Optional[OS]:
shdrs = elf.symtab
if not shdrs:
# executable does not contain a symbol table
# or the symbol's names are stripped
return None
symtab_shdr, strtab_shdr = shdrs
symtab = SymTab(elf.endian, elf.bitness, symtab_shdr, strtab_shdr)
keywords = {
OS.LINUX: [
"linux",
"/linux/",
],
}
for symbol in symtab.get_symbols():
sym_name = symtab.get_name(symbol)
for os, hints in keywords.items():
if any(hint in sym_name for hint in hints):
return os
return None
def detect_elf_os(f) -> str:
"""
f: type Union[BinaryIO, IDAIO, GHIDRAIO]
"""
try:
elf = ELF(f)
except Exception as e:
logger.warning("Error parsing ELF file: %s", e)
return "unknown"
try:
osabi_guess = guess_os_from_osabi(elf)
logger.debug("guess: osabi: %s", osabi_guess)
except Exception as e:
logger.warning("Error guessing OS from OSABI: %s", e)
osabi_guess = None
try:
ph_notes_guess = guess_os_from_ph_notes(elf)
logger.debug("guess: ph notes: %s", ph_notes_guess)
except Exception as e:
logger.warning("Error guessing OS from program header notes: %s", e)
ph_notes_guess = None
try:
sh_notes_guess = guess_os_from_sh_notes(elf)
logger.debug("guess: sh notes: %s", sh_notes_guess)
except Exception as e:
logger.warning("Error guessing OS from section header notes: %s", e)
sh_notes_guess = None
try:
linker_guess = guess_os_from_linker(elf)
logger.debug("guess: linker: %s", linker_guess)
except Exception as e:
logger.warning("Error guessing OS from linker: %s", e)
linker_guess = None
try:
abi_versions_needed_guess = guess_os_from_abi_versions_needed(elf)
logger.debug("guess: ABI versions needed: %s", abi_versions_needed_guess)
except Exception as e:
logger.warning("Error guessing OS from ABI versions needed: %s", e)
abi_versions_needed_guess = None
try:
needed_dependencies_guess = guess_os_from_needed_dependencies(elf)
logger.debug("guess: needed dependencies: %s", needed_dependencies_guess)
except Exception as e:
logger.warning("Error guessing OS from needed dependencies: %s", e)
needed_dependencies_guess = None
try:
symtab_guess = guess_os_from_symtab(elf)
logger.debug("guess: pertinent symbol name: %s", symtab_guess)
except Exception as e:
logger.warning("Error guessing OS from symbol table: %s", e)
symtab_guess = None
ret = None
if osabi_guess:
ret = osabi_guess
elif ph_notes_guess:
ret = ph_notes_guess
elif sh_notes_guess:
ret = sh_notes_guess
elif linker_guess:
ret = linker_guess
elif abi_versions_needed_guess:
ret = abi_versions_needed_guess
elif needed_dependencies_guess:
ret = needed_dependencies_guess
elif symtab_guess:
ret = symtab_guess
return ret.value if ret is not None else "unknown"
def detect_elf_arch(f: BinaryIO) -> str:
return ELF(f).e_machine or "unknown"

View File

@@ -0,0 +1,203 @@
# 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 io
import logging
from typing import Tuple, Iterator
from pathlib import Path
from elftools.elf.elffile import ELFFile, SymbolTableSection
from elftools.elf.relocation import RelocationSection
import capa.features.extractors.common
from capa.features.file import Export, Import, Section
from capa.features.common import OS, FORMAT_ELF, Arch, Format, Feature
from capa.features.address import NO_ADDRESS, FileOffsetAddress, AbsoluteVirtualAddress
from capa.features.extractors.base_extractor import SampleHashes, StaticFeatureExtractor
logger = logging.getLogger(__name__)
def extract_file_export_names(elf: ELFFile, **kwargs):
for section in elf.iter_sections():
if not isinstance(section, SymbolTableSection):
continue
if section["sh_entsize"] == 0:
logger.debug("Symbol table '%s' has a sh_entsize of zero!", section.name)
continue
logger.debug("Symbol table '%s' contains %s entries:", section.name, section.num_symbols())
for symbol in section.iter_symbols():
# The following conditions are based on the following article
# http://www.m4b.io/elf/export/binary/analysis/2015/05/25/what-is-an-elf-export.html
if not symbol.name:
continue
if symbol.entry.st_info.type not in ["STT_FUNC", "STT_OBJECT", "STT_IFUNC"]:
continue
if symbol.entry.st_value == 0:
continue
if symbol.entry.st_shndx == "SHN_UNDEF":
continue
yield Export(symbol.name), AbsoluteVirtualAddress(symbol.entry.st_value)
def extract_file_import_names(elf: ELFFile, **kwargs):
# Create a dictionary to store symbol names by their index
symbol_names = {}
# Extract symbol names and store them in the dictionary
for section in elf.iter_sections():
if not isinstance(section, SymbolTableSection):
continue
for _, symbol in enumerate(section.iter_symbols()):
# The following conditions are based on the following article
# http://www.m4b.io/elf/export/binary/analysis/2015/05/25/what-is-an-elf-export.html
if not symbol.name:
continue
if symbol.entry.st_info.type not in ["STT_FUNC", "STT_OBJECT", "STT_IFUNC"]:
continue
if symbol.entry.st_value != 0:
continue
if symbol.entry.st_shndx != "SHN_UNDEF":
continue
if symbol.entry.st_name == 0:
continue
symbol_names[_] = symbol.name
for section in elf.iter_sections():
if not isinstance(section, RelocationSection):
continue
if section["sh_entsize"] == 0:
logger.debug("Symbol table '%s' has a sh_entsize of zero!", section.name)
continue
logger.debug("Symbol table '%s' contains %s entries:", section.name, section.num_relocations())
for relocation in section.iter_relocations():
# Extract the symbol name from the symbol table using the symbol index in the relocation
if relocation["r_info_sym"] not in symbol_names:
continue
yield Import(symbol_names[relocation["r_info_sym"]]), FileOffsetAddress(relocation["r_offset"])
def extract_file_section_names(elf: ELFFile, **kwargs):
for section in elf.iter_sections():
if section.name:
yield Section(section.name), AbsoluteVirtualAddress(section.header.sh_addr)
elif section.is_null():
yield Section("NULL"), AbsoluteVirtualAddress(section.header.sh_addr)
def extract_file_strings(buf, **kwargs):
yield from capa.features.extractors.common.extract_file_strings(buf)
def extract_file_os(elf: ELFFile, buf, **kwargs):
# our current approach does not always get an OS value, e.g. for packed samples
# for file limitation purposes, we're more lax here
try:
os_tuple = next(capa.features.extractors.common.extract_os(buf))
yield os_tuple
except StopIteration:
yield OS("unknown"), NO_ADDRESS
def extract_file_format(**kwargs):
yield Format(FORMAT_ELF), NO_ADDRESS
def extract_file_arch(elf: ELFFile, **kwargs):
arch = elf.get_machine_arch()
if arch == "x86":
yield Arch("i386"), NO_ADDRESS
elif arch == "x64":
yield Arch("amd64"), NO_ADDRESS
else:
logger.warning("unsupported architecture: %s", arch)
def extract_file_features(elf: ELFFile, buf: bytes) -> Iterator[Tuple[Feature, int]]:
for file_handler in FILE_HANDLERS:
for feature, addr in file_handler(elf=elf, buf=buf): # type: ignore
yield feature, addr
FILE_HANDLERS = (
extract_file_export_names,
extract_file_import_names,
extract_file_section_names,
extract_file_strings,
# no library matching
extract_file_format,
)
def extract_global_features(elf: ELFFile, buf: bytes) -> Iterator[Tuple[Feature, int]]:
for global_handler in GLOBAL_HANDLERS:
for feature, addr in global_handler(elf=elf, buf=buf): # type: ignore
yield feature, addr
GLOBAL_HANDLERS = (
extract_file_os,
extract_file_arch,
)
class ElfFeatureExtractor(StaticFeatureExtractor):
def __init__(self, path: Path):
super().__init__(SampleHashes.from_bytes(path.read_bytes()))
self.path: Path = path
self.elf = ELFFile(io.BytesIO(path.read_bytes()))
def get_base_address(self):
# virtual address of the first segment with type LOAD
for segment in self.elf.iter_segments():
if segment.header.p_type == "PT_LOAD":
return AbsoluteVirtualAddress(segment.header.p_vaddr)
def extract_global_features(self):
buf = self.path.read_bytes()
for feature, addr in extract_global_features(self.elf, buf):
yield feature, addr
def extract_file_features(self):
buf = self.path.read_bytes()
for feature, addr in extract_file_features(self.elf, buf):
yield feature, addr
def get_functions(self):
raise NotImplementedError("ElfFeatureExtractor can only be used to extract file features")
def extract_function_features(self, f):
raise NotImplementedError("ElfFeatureExtractor can only be used to extract file features")
def get_basic_blocks(self, f):
raise NotImplementedError("ElfFeatureExtractor can only be used to extract file features")
def extract_basic_block_features(self, f, bb):
raise NotImplementedError("ElfFeatureExtractor can only be used to extract file features")
def get_instructions(self, f, bb):
raise NotImplementedError("ElfFeatureExtractor can only be used to extract file features")
def extract_insn_features(self, f, bb, insn):
raise NotImplementedError("ElfFeatureExtractor can only be used to extract file features")
def is_library_function(self, addr):
raise NotImplementedError("ElfFeatureExtractor can only be used to extract file features")
def get_function_name(self, addr):
raise NotImplementedError("ElfFeatureExtractor can only be used to extract file features")

View File

@@ -0,0 +1,152 @@
# 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
import capa.features.extractors.ghidra.helpers
from capa.features.common import Feature, Characteristic
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
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("<B", op_val & 0xFF)
elif op_bit_len == 16:
chars = struct.pack("<H", op_val & 0xFFFF)
elif op_bit_len == 32:
chars = struct.pack("<I", op_val & 0xFFFFFFFF)
elif op_bit_len == 64:
chars = struct.pack("<Q", op_val & 0xFFFFFFFFFFFFFFFF)
else:
raise ValueError(f"Unhandled operand data type 0x{op_bit_len:x}.")
def is_printable_ascii(chars_: bytes):
return all(c < 127 and chr(c) in string.printable for c in chars_)
def is_printable_utf16le(chars_: bytes):
if all(c == 0x00 for c in chars_[1::2]):
return is_printable_ascii(chars_[::2])
if is_printable_ascii(chars):
return op_byte_len
if is_printable_utf16le(chars):
return op_byte_len
return 0
def is_mov_imm_to_stack(insn: ghidra.program.database.code.InstructionDB) -> 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 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:
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
"""
# 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()
return False
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"), bbh.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"), bbh.address
BASIC_BLOCK_HANDLERS = (
extract_bb_tight_loop,
extract_bb_stackstring,
)
def extract_features(fh: FunctionHandle, bbh: BBHandle) -> 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(), bbh.address
for bb_handler in BASIC_BLOCK_HANDLERS:
for feature, addr in bb_handler(fh, bbh):
yield feature, addr
def main():
features = []
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)))
import pprint
pprint.pprint(features) # noqa: T203
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,93 @@
# 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, 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 (
BBHandle,
InsnHandle,
SampleHashes,
FunctionHandle,
StaticFeatureExtractor,
)
class GhidraFeatureExtractor(StaticFeatureExtractor):
def __init__(self):
import capa.features.extractors.ghidra.helpers as ghidra_helpers
super().__init__(
SampleHashes(
md5=capa.ghidra.helpers.get_file_md5(),
# ghidra doesn't expose this hash.
# https://ghidra.re/ghidra_docs/api/ghidra/program/model/listing/Program.html
#
# the hashes are stored in the database, not computed on the fly,
# so its probably not trivial to add SHA1.
sha1="",
sha256=capa.ghidra.helpers.get_file_sha256(),
)
)
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
def extract_global_features(self):
yield from self.global_features
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
for fhandle in ghidra_helpers.get_function_symbols():
fh: FunctionHandle = FunctionHandle(
address=AbsoluteVirtualAddress(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:
func = getFunctionContaining(toAddr(addr)) # type: ignore [name-defined] # noqa: F821
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)
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)

View File

@@ -0,0 +1,202 @@
# 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 re
import struct
from typing import List, Tuple, Iterator
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
MAX_OFFSET_PE_AFTER_MZ = 0x200
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
"""
todo = []
for mzx, pex, i in mz_xor:
for match in re.finditer(re.escape(mzx), block_bytez):
todo.append((match.start(), mzx, pex, i))
seg_max = len(block_bytez) # 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 + 0x3C
if seg_max < e_lfanew + 4:
continue
e_lfanew_bytes = block_bytez[e_lfanew : e_lfanew + 4]
newoff = struct.unpack("<I", capa.features.extractors.helpers.xor_static(e_lfanew_bytes, i))[0]
# assume XOR'd "PE" bytes exist within threshold
if newoff > MAX_OFFSET_PE_AFTER_MZ:
continue
peoff = off + newoff
if seg_max < peoff + 2:
continue
pe_bytes = block_bytez[peoff : peoff + 2]
if pe_bytes == pex:
yield off, i
def extract_file_embedded_pe() -> Iterator[Tuple[Feature, Address]]:
"""extract embedded PE features"""
# 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]]:
"""extract function exports"""
st = currentProgram().getSymbolTable() # type: ignore [name-defined] # noqa: F821
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(): # 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], include_dll=True):
yield Import(name), AbsoluteVirtualAddress(addr)
def extract_file_section_names() -> Iterator[Tuple[Feature, Address]]:
"""extract section names"""
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
if block.isInitialized():
p_bytes = capa.features.extractors.ghidra.helpers.get_block_bytes(block)
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): # 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:<function-name>
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() # type: ignore [name-defined] # noqa: F821
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())) # noqa: T203
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,73 @@
# 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 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
def extract_function_calls_to(fh: FunctionHandle):
"""extract callers to a function"""
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: 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
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(f.getEntryPoint().getOffset())
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
if func.getEntryPoint().getOffset() == f.getEntryPoint().getOffset():
yield Characteristic("recursive call"), AbsoluteVirtualAddress(f.getEntryPoint().getOffset())
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
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) # noqa: T203
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,67 @@
# 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 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
logger = logging.getLogger(__name__)
def extract_os() -> Iterator[Tuple[Feature, Address]]:
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:
with contextlib.closing(capa.ghidra.helpers.GHIDRAIO()) 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
def extract_arch() -> Iterator[Tuple[Feature, Address]]:
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
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

View File

@@ -0,0 +1,277 @@
# 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 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
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
def ints_to_bytes(bytez: List[int]) -> bytes:
"""convert Java signed ints to Python bytes
args:
bytez: list of Java signed ints
"""
return bytes([b & 0xFF for b in bytez])
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])
eas = findBytes(addr, seqstr, java.lang.Integer.MAX_VALUE, 1) # type: ignore [name-defined] # noqa: F821
yield from eas
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
"""
try:
return ints_to_bytes(getBytes(addr, length)) # type: ignore [name-defined] # noqa: F821
except RuntimeError:
return b""
def get_block_bytes(block: ghidra.program.model.mem.MemoryBlock) -> bytes:
"""yield all bytes in a given block
args:
block: MemoryBlock to pull from
"""
return get_bytes(block.getStart(), block.getSize())
def get_function_symbols():
"""yield all non-external function symbols"""
yield from currentProgram().getFunctionManager().getFunctionsNoStubs(True) # type: ignore [name-defined] # noqa: F821
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"""
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]]:
"""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
ex_loc = f.getExternalLocation().getAddress() # map external locations as well (offset into module files)
fstr = f.toString().split("::") # format: MODULE.dll::import / MODULE::Ordinal_* / <EXTERNAL>::import
if "Ordinal_" in fstr[1]:
fstr[1] = f"#{fstr[1].split('_')[1]}"
# <EXTERNAL> mostly shows up in ELF files, otherwise, strip '.dll' w/ [:-4]
fstr[0] = "*" if "<EXTERNAL>" 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
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:<function-name>
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 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]],
) -> 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
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"""
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())
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 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():
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

View File

@@ -0,0 +1,521 @@
# 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 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
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 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)
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):
# 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 = fakes.get(op_ref) # obtain the real addr
if not ref:
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
addr_ref = capa.features.extractors.ghidra.helpers.dereference_ptr(insn)
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:
return # cannot resolve dynamics statically
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, fakes, imports, externs):
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: 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
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, 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, fakes, imports, False):
for ext in api:
yield API(ext), ih.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
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()):
# 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
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: 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
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
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), 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]]:
"""
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
ref = insn.getAddress() # init to insn addr
for i in range(insn.getNumOperands()):
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
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), ih.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
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
if ghidra_dat and ghidra_dat.hasStringValue():
yield String(ghidra_dat.getValue()), ih.address
def extract_insn_mnemonic_features(
fh: FunctionHandle, bb: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction mnemonic features"""
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: 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
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"), ih.address
def extract_insn_segment_access_features(
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"), ih.address
if "GS:" in insn_str:
yield Characteristic("gs access"), ih.address
def extract_insn_peb_access_characteristic_features(
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"), ih.address
def extract_insn_cross_section_cflow(
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
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
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, 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, fakes, imports, externs):
return
elif ref_type == OperandType.DYNAMIC | OperandType.ADDRESS or ref_type == OperandType.DYNAMIC:
return # cannot resolve dynamics statically
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, fakes, imports, externs):
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"), ih.address
def extract_function_calls_from(
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
# 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: 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
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.isRegister(insn.getOperandType(0)):
yield Characteristic("indirect call"), ih.address
if OperandType.isIndirect(insn.getOperandType(0)):
yield Characteristic("indirect call"), ih.address
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() # 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:
return insn_addr > last_addr.add(SECURITY_COOKIE_BYTES_DELTA * -1)
else:
return False
def extract_insn_nzxor_characteristic_features(
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(f, insn):
return
yield Characteristic("nzxor"), ih.address
def extract_features(
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):
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():
""" """
features = []
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)))
import pprint
pprint.pprint(features) # noqa: T203
if __name__ == "__main__":
main()

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2020 FireEye, 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
@@ -6,70 +6,104 @@
# 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 struct
import builtins
from capa.features.insn import API
from typing import Tuple, Iterator
MIN_STACKSTRING_LEN = 8
def xor_static(data, i):
if sys.version_info >= (3, 0):
return bytes(c ^ i for c in data)
else:
return "".join(chr(ord(c) ^ i) for c in data)
def xor_static(data: bytes, i: int) -> bytes:
return bytes(c ^ i for c in data)
def is_aw_function(function_name):
def is_aw_function(symbol: str) -> bool:
"""
is the given function name an A/W function?
these are variants of functions that, on Windows, accept either a narrow or wide string.
"""
if len(function_name) < 2:
if len(symbol) < 2:
return False
# last character should be 'A' or 'W'
if function_name[-1] not in ("A", "W"):
if symbol[-1] not in ("A", "W"):
return False
# second to last character should be lowercase letter
return "a" <= function_name[-2] <= "z" or "0" <= function_name[-2] <= "9"
return True
def generate_api_features(apiname, va):
def is_ordinal(symbol: str) -> bool:
"""
for a given function name and address, generate API names.
is the given symbol an ordinal that is prefixed by "#"?
"""
if symbol:
return symbol[0] == "#"
return False
def generate_symbols(dll: str, symbol: str, include_dll=False) -> Iterator[str]:
"""
for a given dll and symbol name, generate variants.
we over-generate features to make matching easier.
these include:
- kernel32.CreateFileA
- kernel32.CreateFile
- CreateFileA
- CreateFile
- ws2_32.#1
note that since capa v7 only `import` features and APIs called via ordinal include DLL names:
- kernel32.CreateFileA
- kernel32.CreateFile
- ws2_32.#1
for `api` features dll names are good for documentation but not used during matching
"""
# (kernel32.CreateFileA, 0x401000)
yield API(apiname), va
# normalize dll name
dll = dll.lower()
if is_aw_function(apiname):
# (kernel32.CreateFile, 0x401000)
yield API(apiname[:-1]), va
# trim extensions observed in dynamic traces
dll = dll[0:-4] if dll.endswith(".dll") else dll
dll = dll[0:-4] if dll.endswith(".drv") else dll
if "." in apiname:
modname, impname = apiname.split(".")
# strip modname to support importname-only matching
# (CreateFileA, 0x401000)
yield API(impname), va
if include_dll or is_ordinal(symbol):
# ws2_32.#1
# kernel32.CreateFileA
yield f"{dll}.{symbol}"
if is_aw_function(impname):
# (CreateFile, 0x401000)
yield API(impname[:-1]), va
if not is_ordinal(symbol):
# CreateFileA
yield symbol
if is_aw_function(symbol):
if include_dll:
# kernel32.CreateFile
yield f"{dll}.{symbol[:-1]}"
# CreateFile
yield symbol[:-1]
def all_zeros(bytez):
def reformat_forwarded_export_name(forwarded_name: str) -> str:
"""
a forwarded export has a DLL name/path and symbol name.
we want the former to be lowercase, and the latter to be verbatim.
"""
# use rpartition so we can split on separator between dll and name.
# the dll name can be a full path, like in the case of
# ef64d6d7c34250af8e21a10feb931c9b
# which i assume means the path can have embedded periods.
# so we don't want the first period, we want the last.
forwarded_dll, _, forwarded_symbol = forwarded_name.rpartition(".")
forwarded_dll = forwarded_dll.lower()
return f"{forwarded_dll}.{forwarded_symbol}"
def all_zeros(bytez: bytes) -> bool:
return all(b == 0 for b in builtins.bytes(bytez))
def twos_complement(val, bits):
def twos_complement(val: int, bits: int) -> int:
"""
compute the 2's complement of int value val
@@ -82,3 +116,48 @@ def twos_complement(val, bits):
else:
# return positive value as is
return val
def carve_pe(pbytes: bytes, offset: int = 0) -> Iterator[Tuple[int, int]]:
"""
Generate (offset, key) tuples of embedded PEs
Based on the version from vivisect:
https://github.com/vivisect/vivisect/blob/7be4037b1cecc4551b397f840405a1fc606f9b53/PE/carve.py#L19
And its IDA adaptation:
capa/features/extractors/ida/file.py
"""
mz_xor = [
(
xor_static(b"MZ", key),
xor_static(b"PE", key),
key,
)
for key in range(256)
]
pblen = len(pbytes)
todo = [(pbytes.find(mzx, offset), mzx, pex, key) for mzx, pex, key in mz_xor]
todo = [(off, mzx, pex, key) for (off, mzx, pex, key) in todo if off != -1]
while len(todo):
off, mzx, pex, key = todo.pop()
# The MZ header has one field we will check
# e_lfanew is at 0x3c
e_lfanew = off + 0x3C
if pblen < (e_lfanew + 4):
continue
newoff = struct.unpack("<I", xor_static(pbytes[e_lfanew : e_lfanew + 4], key))[0]
nextres = pbytes.find(mzx, off + 1)
if nextres != -1:
todo.append((nextres, mzx, pex, key))
peoff = off + newoff
if pblen < (peoff + 2):
continue
if pbytes[peoff : peoff + 2] == pex:
yield (off, key)

View File

@@ -1,93 +0,0 @@
# Copyright (C) 2020 FireEye, 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 types
import idaapi
import capa.features.extractors.ida.file
import capa.features.extractors.ida.insn
import capa.features.extractors.ida.function
import capa.features.extractors.ida.basicblock
from capa.features.extractors import FeatureExtractor
def get_ea(self):
""" """
if isinstance(self, (idaapi.BasicBlock, idaapi.func_t)):
return self.start_ea
if isinstance(self, idaapi.insn_t):
return self.ea
raise TypeError
def add_ea_int_cast(o):
"""
dynamically add a cast-to-int (`__int__`) method to the given object
that returns the value of the `.ea` property.
this bit of skullduggery lets use cast viv-utils objects as ints.
the correct way of doing this is to update viv-utils (or subclass the objects here).
"""
if sys.version_info[0] >= 3:
setattr(o, "__int__", types.MethodType(get_ea, o))
else:
setattr(o, "__int__", types.MethodType(get_ea, o, type(o)))
return o
class IdaFeatureExtractor(FeatureExtractor):
def __init__(self):
super(IdaFeatureExtractor, self).__init__()
def get_base_address(self):
return idaapi.get_imagebase()
def extract_file_features(self):
for (feature, ea) in capa.features.extractors.ida.file.extract_features():
yield feature, ea
def get_functions(self):
import capa.features.extractors.ida.helpers as ida_helpers
# data structure shared across functions yielded here.
# useful for caching analysis relevant across a single workspace.
ctx = {}
# ignore library functions and thunk functions as identified by IDA
for f in ida_helpers.get_functions(skip_thunks=True, skip_libs=True):
setattr(f, "ctx", ctx)
yield add_ea_int_cast(f)
@staticmethod
def get_function(ea):
f = idaapi.get_func(ea)
setattr(f, "ctx", {})
return add_ea_int_cast(f)
def extract_function_features(self, f):
for (feature, ea) in capa.features.extractors.ida.function.extract_features(f):
yield feature, ea
def get_basic_blocks(self, f):
for bb in capa.features.extractors.ida.helpers.get_function_blocks(f):
yield add_ea_int_cast(bb)
def extract_basic_block_features(self, f, bb):
for (feature, ea) in capa.features.extractors.ida.basicblock.extract_features(f, bb):
yield feature, ea
def get_instructions(self, f, bb):
import capa.features.extractors.ida.helpers as ida_helpers
for insn in ida_helpers.get_instructions_in_range(bb.start_ea, bb.end_ea):
yield add_ea_int_cast(insn)
def extract_insn_features(self, f, bb, insn):
for (feature, ea) in capa.features.extractors.ida.insn.extract_features(f, bb, insn):
yield feature, ea

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2020 FireEye, 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
@@ -6,25 +6,23 @@
# 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 string
import struct
from typing import Tuple, Iterator
import idaapi
import capa.features.extractors.ida.helpers
from capa.features import Characteristic
from capa.features.common import Feature, Characteristic
from capa.features.address import Address
from capa.features.basicblock import BasicBlock
from capa.features.extractors.ida import helpers
from capa.features.extractors.helpers import MIN_STACKSTRING_LEN
from capa.features.extractors.base_extractor import BBHandle, FunctionHandle
def get_printable_len(op):
"""Return string length if all operand bytes are ascii or utf16-le printable
args:
op (IDA op_t)
"""
def get_printable_len(op: idaapi.op_t) -> int:
"""Return string length if all operand bytes are ascii or utf16-le printable"""
op_val = capa.features.extractors.ida.helpers.mask_op_val(op)
if op.dtype == idaapi.dt_byte:
@@ -36,21 +34,14 @@ def get_printable_len(op):
elif op.dtype == idaapi.dt_qword:
chars = struct.pack("<Q", op_val)
else:
raise ValueError("Unhandled operand data type 0x%x." % op.dtype)
raise ValueError(f"Unhandled operand data type 0x{op.dtype:x}.")
def is_printable_ascii(chars):
if sys.version_info[0] >= 3:
return all(c < 127 and chr(c) in string.printable for c in chars)
else:
return all(ord(c) < 127 and c in string.printable for c in chars)
def is_printable_ascii(chars_: bytes):
return all(c < 127 and chr(c) in string.printable for c in chars_)
def is_printable_utf16le(chars):
if sys.version_info[0] >= 3:
if all(c == 0x00 for c in chars[1::2]):
return is_printable_ascii(chars[::2])
else:
if all(c == "\x00" for c in chars[1::2]):
return is_printable_ascii(chars[::2])
def is_printable_utf16le(chars_: bytes):
if all(c == 0x00 for c in chars_[1::2]):
return is_printable_ascii(chars_[::2])
if is_printable_ascii(chars):
return idaapi.get_dtype_size(op.dtype)
@@ -61,12 +52,8 @@ def get_printable_len(op):
return 0
def is_mov_imm_to_stack(insn):
"""verify instruction moves immediate onto stack
args:
insn (IDA insn_t)
"""
def is_mov_imm_to_stack(insn: idaapi.insn_t) -> bool:
"""verify instruction moves immediate onto stack"""
if insn.Op2.type != idaapi.o_imm:
return False
@@ -79,14 +66,10 @@ def is_mov_imm_to_stack(insn):
return True
def bb_contains_stackstring(f, bb):
def bb_contains_stackstring(f: idaapi.func_t, bb: idaapi.BasicBlock) -> bool:
"""check basic block for stackstring indicators
true if basic block contains enough moves of constant bytes to the stack
args:
f (IDA func_t)
bb (IDA BasicBlock)
"""
count = 0
for insn in capa.features.extractors.ida.helpers.get_instructions_in_range(bb.start_ea, bb.end_ea):
@@ -97,57 +80,27 @@ def bb_contains_stackstring(f, bb):
return False
def extract_bb_stackstring(f, bb):
"""extract stackstring indicators from basic block
args:
f (IDA func_t)
bb (IDA BasicBlock)
"""
if bb_contains_stackstring(f, bb):
yield Characteristic("stack string"), bb.start_ea
def extract_bb_stackstring(fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""extract stackstring indicators from basic block"""
if bb_contains_stackstring(fh.inner, bbh.inner):
yield Characteristic("stack string"), bbh.address
def extract_bb_tight_loop(f, bb):
"""extract tight loop indicators from a basic block
args:
f (IDA func_t)
bb (IDA BasicBlock)
"""
if capa.features.extractors.ida.helpers.is_basic_block_tight_loop(bb):
yield Characteristic("tight loop"), bb.start_ea
def extract_bb_tight_loop(fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""extract tight loop indicators from a basic block"""
if capa.features.extractors.ida.helpers.is_basic_block_tight_loop(bbh.inner):
yield Characteristic("tight loop"), bbh.address
def extract_features(f, bb):
"""extract basic block features
args:
f (IDA func_t)
bb (IDA BasicBlock)
"""
def extract_features(fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""extract basic block features"""
for bb_handler in BASIC_BLOCK_HANDLERS:
for (feature, ea) in bb_handler(f, bb):
yield feature, ea
yield BasicBlock(), bb.start_ea
for feature, addr in bb_handler(fh, bbh):
yield feature, addr
yield BasicBlock(), bbh.address
BASIC_BLOCK_HANDLERS = (
extract_bb_tight_loop,
extract_bb_stackstring,
)
def main():
features = []
for f in helpers.get_functions(skip_thunks=True, skip_libs=True):
for bb in idaapi.FlowChart(f, flags=idaapi.FC_PREDS):
features.extend(list(extract_features(f, bb)))
import pprint
pprint.pprint(features)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,82 @@
# 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, Iterator
import idaapi
import ida_nalt
import capa.ida.helpers
import capa.features.extractors.elf
import capa.features.extractors.ida.file
import capa.features.extractors.ida.insn
import capa.features.extractors.ida.global_
import capa.features.extractors.ida.function
import capa.features.extractors.ida.basicblock
from capa.features.common import Feature
from capa.features.address import Address, AbsoluteVirtualAddress
from capa.features.extractors.base_extractor import (
BBHandle,
InsnHandle,
SampleHashes,
FunctionHandle,
StaticFeatureExtractor,
)
class IdaFeatureExtractor(StaticFeatureExtractor):
def __init__(self):
super().__init__(
hashes=SampleHashes(
md5=ida_nalt.retrieve_input_file_md5(), sha1="(unknown)", sha256=ida_nalt.retrieve_input_file_sha256()
)
)
self.global_features: List[Tuple[Feature, Address]] = []
self.global_features.extend(capa.features.extractors.ida.file.extract_file_format())
self.global_features.extend(capa.features.extractors.ida.global_.extract_os())
self.global_features.extend(capa.features.extractors.ida.global_.extract_arch())
def get_base_address(self):
return AbsoluteVirtualAddress(idaapi.get_imagebase())
def extract_global_features(self):
yield from self.global_features
def extract_file_features(self):
yield from capa.features.extractors.ida.file.extract_features()
def get_functions(self) -> Iterator[FunctionHandle]:
import capa.features.extractors.ida.helpers as ida_helpers
# ignore library functions and thunk functions as identified by IDA
yield from ida_helpers.get_functions(skip_thunks=True, skip_libs=True)
@staticmethod
def get_function(ea: int) -> FunctionHandle:
f = idaapi.get_func(ea)
return FunctionHandle(address=AbsoluteVirtualAddress(f.start_ea), inner=f)
def extract_function_features(self, fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.ida.function.extract_features(fh)
def get_basic_blocks(self, fh: FunctionHandle) -> Iterator[BBHandle]:
import capa.features.extractors.ida.helpers as ida_helpers
for bb in ida_helpers.get_function_blocks(fh.inner):
yield BBHandle(address=AbsoluteVirtualAddress(bb.start_ea), inner=bb)
def extract_basic_block_features(self, fh: FunctionHandle, bbh: BBHandle) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.ida.basicblock.extract_features(fh, bbh)
def get_instructions(self, fh: FunctionHandle, bbh: BBHandle) -> Iterator[InsnHandle]:
import capa.features.extractors.ida.helpers as ida_helpers
for insn in ida_helpers.get_instructions_in_range(bbh.inner.start_ea, bbh.inner.end_ea):
yield InsnHandle(address=AbsoluteVirtualAddress(insn.ea), inner=insn)
def extract_insn_features(self, fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle):
yield from capa.features.extractors.ida.insn.extract_features(fh, bbh, ih)

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2020 FireEye, 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
@@ -7,26 +7,29 @@
# See the License for the specific language governing permissions and limitations under the License.
import struct
from typing import Tuple, Iterator
import idc
import idaapi
import idautils
import ida_entry
import capa.features.extractors.common
import capa.features.extractors.helpers
import capa.features.extractors.strings
import capa.features.extractors.ida.helpers
from capa.features import String, Characteristic
from capa.features.file import Export, Import, Section
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
MAX_OFFSET_PE_AFTER_MZ = 0x200
def check_segment_for_pe(seg):
def check_segment_for_pe(seg: idaapi.segment_t) -> Iterator[Tuple[int, int]]:
"""check segment for embedded PE
adapted for IDA from:
https://github.com/vivisect/vivisect/blob/7be4037b1cecc4551b397f840405a1fc606f9b53/PE/carve.py#L19
args:
seg (IDA segment_t)
https://github.com/vivisect/vivisect/blob/91e8419a861f49779f18316f155311967e696836/PE/carve.py#L25
"""
seg_max = seg.end_ea
mz_xor = [
@@ -37,16 +40,17 @@ def check_segment_for_pe(seg):
)
for i in range(256)
]
todo = [
(capa.features.extractors.ida.helpers.find_byte_sequence(seg.start_ea, seg.end_ea, mzx), mzx, pex, i)
for mzx, pex, i in mz_xor
]
todo = [(off, mzx, pex, i) for (off, mzx, pex, i) in todo if off != idaapi.BADADDR]
todo = []
for mzx, pex, i in mz_xor:
# find all segment offsets containing XOR'd "MZ" bytes
for off in capa.features.extractors.ida.helpers.find_byte_sequence(seg.start_ea, seg.end_ea, mzx):
todo.append((off, mzx, pex, i))
while len(todo):
off, mzx, pex, i = todo.pop()
# The MZ header has one field we will check e_lfanew is at 0x3c
# MZ header has one field we will check e_lfanew is at 0x3c
e_lfanew = off + 0x3C
if seg_max < (e_lfanew + 4):
@@ -54,19 +58,19 @@ def check_segment_for_pe(seg):
newoff = struct.unpack("<I", capa.features.extractors.helpers.xor_static(idc.get_bytes(e_lfanew, 4), i))[0]
# assume XOR'd "PE" bytes exist within threshold
if newoff > MAX_OFFSET_PE_AFTER_MZ:
continue
peoff = off + newoff
if seg_max < (peoff + 2):
continue
if idc.get_bytes(peoff, 2) == pex:
yield (off, i)
nextres = capa.features.extractors.ida.helpers.find_byte_sequence(off + 1, seg.end_ea, mzx)
if nextres != -1:
todo.append((nextres, mzx, pex, i))
yield off, i
def extract_file_embedded_pe():
def extract_file_embedded_pe() -> Iterator[Tuple[Feature, Address]]:
"""extract embedded PE features
IDA must load resource sections for this to be complete
@@ -74,17 +78,23 @@ def extract_file_embedded_pe():
- Check 'Load resource sections' when opening binary in IDA manually
"""
for seg in capa.features.extractors.ida.helpers.get_segments(skip_header_segments=True):
for (ea, _) in check_segment_for_pe(seg):
yield Characteristic("embedded pe"), ea
for ea, _ in check_segment_for_pe(seg):
yield Characteristic("embedded pe"), FileOffsetAddress(ea)
def extract_file_export_names():
""" extract function exports """
for (_, _, ea, name) in idautils.Entries():
yield Export(name), ea
def extract_file_export_names() -> Iterator[Tuple[Feature, Address]]:
"""extract function exports"""
for _, ordinal, ea, name in idautils.Entries():
forwarded_name = ida_entry.get_entry_forwarder(ordinal)
if forwarded_name is None:
yield Export(name), AbsoluteVirtualAddress(ea)
else:
forwarded_name = capa.features.extractors.helpers.reformat_forwarded_export_name(forwarded_name)
yield Export(forwarded_name), AbsoluteVirtualAddress(ea)
yield Characteristic("forwarded export"), AbsoluteVirtualAddress(ea)
def extract_file_import_names():
def extract_file_import_names() -> Iterator[Tuple[Feature, Address]]:
"""extract function imports
1. imports by ordinal:
@@ -95,15 +105,32 @@ def extract_file_import_names():
- modulename.importname
- importname
"""
for (ea, info) in capa.features.extractors.ida.helpers.get_file_imports().items():
if info[1]:
yield Import("%s.%s" % (info[0], info[1])), ea
yield Import(info[1]), ea
if info[2]:
yield Import("%s.#%s" % (info[0], str(info[2]))), ea
for ea, info in capa.features.extractors.ida.helpers.get_file_imports().items():
addr = AbsoluteVirtualAddress(ea)
if info[1] and info[2]:
# e.g. in mimikatz: ('cabinet', 'FCIAddFile', 11L)
# extract by name here and by ordinal below
for name in capa.features.extractors.helpers.generate_symbols(info[0], info[1], include_dll=True):
yield Import(name), addr
dll = info[0]
symbol = f"#{info[2]}"
elif info[1]:
dll = info[0]
symbol = info[1]
elif info[2]:
dll = info[0]
symbol = f"#{info[2]}"
else:
continue
for name in capa.features.extractors.helpers.generate_symbols(dll, symbol, include_dll=True):
yield Import(name), addr
for ea, info in capa.features.extractors.ida.helpers.get_file_externs().items():
yield Import(info[1]), AbsoluteVirtualAddress(ea)
def extract_file_section_names():
def extract_file_section_names() -> Iterator[Tuple[Feature, Address]]:
"""extract section names
IDA must load resource sections for this to be complete
@@ -111,10 +138,10 @@ def extract_file_section_names():
- Check 'Load resource sections' when opening binary in IDA manually
"""
for seg in capa.features.extractors.ida.helpers.get_segments(skip_header_segments=True):
yield Section(idaapi.get_segm_name(seg)), seg.start_ea
yield Section(idaapi.get_segm_name(seg)), AbsoluteVirtualAddress(seg.start_ea)
def extract_file_strings():
def extract_file_strings() -> Iterator[Tuple[Feature, Address]]:
"""extract ASCII and UTF-16 LE strings
IDA must load resource sections for this to be complete
@@ -124,18 +151,50 @@ def extract_file_strings():
for seg in capa.features.extractors.ida.helpers.get_segments():
seg_buff = capa.features.extractors.ida.helpers.get_segment_buffer(seg)
# differing to common string extractor factor in segment offset here
for s in capa.features.extractors.strings.extract_ascii_strings(seg_buff):
yield String(s.s), (seg.start_ea + s.offset)
yield String(s.s), FileOffsetAddress(seg.start_ea + s.offset)
for s in capa.features.extractors.strings.extract_unicode_strings(seg_buff):
yield String(s.s), (seg.start_ea + s.offset)
yield String(s.s), FileOffsetAddress(seg.start_ea + s.offset)
def extract_features():
""" extract file features """
def extract_file_function_names() -> Iterator[Tuple[Feature, Address]]:
"""
extract the names of statically-linked library functions.
"""
for ea in idautils.Functions():
addr = AbsoluteVirtualAddress(ea)
if idaapi.get_func(ea).flags & idaapi.FUNC_LIB:
name = idaapi.get_name(ea)
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]]:
file_info = idaapi.get_inf_structure()
if file_info.filetype in (idaapi.f_PE, idaapi.f_COFF):
yield Format(FORMAT_PE), NO_ADDRESS
elif file_info.filetype == idaapi.f_ELF:
yield Format(FORMAT_ELF), NO_ADDRESS
elif file_info.filetype == idaapi.f_BIN:
# no file type to return when processing a binary file, but we want to continue processing
return
else:
raise NotImplementedError(f"unexpected file format: {file_info.filetype}")
def extract_features() -> Iterator[Tuple[Feature, Address]]:
"""extract file features"""
for file_handler in FILE_HANDLERS:
for feature, va in file_handler():
yield feature, va
for feature, addr in file_handler():
yield feature, addr
FILE_HANDLERS = (
@@ -144,15 +203,6 @@ FILE_HANDLERS = (
extract_file_strings,
extract_file_section_names,
extract_file_embedded_pe,
extract_file_function_names,
extract_file_format,
)
def main():
""" """
import pprint
pprint.pprint(list(extract_features()))
if __name__ == "__main__":
main()

View File

@@ -1,35 +1,31 @@
# Copyright (C) 2020 FireEye, 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 Tuple, Iterator
import idaapi
import idautils
import capa.features.extractors.ida.helpers
from capa.features import Characteristic
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
def extract_function_calls_to(f):
"""extract callers to a function
args:
f (IDA func_t)
"""
for ea in idautils.CodeRefsTo(f.start_ea, True):
yield Characteristic("calls to"), ea
def extract_function_calls_to(fh: FunctionHandle):
"""extract callers to a function"""
for ea in idautils.CodeRefsTo(fh.inner.start_ea, True):
yield Characteristic("calls to"), AbsoluteVirtualAddress(ea)
def extract_function_loop(f):
"""extract loop indicators from a function
args:
f (IDA func_t)
"""
def extract_function_loop(fh: FunctionHandle):
"""extract loop indicators from a function"""
f: idaapi.func_t = fh.inner
edges = []
# construct control flow graph
@@ -38,43 +34,19 @@ def extract_function_loop(f):
edges.append((bb.start_ea, succ.start_ea))
if loops.has_loop(edges):
yield Characteristic("loop"), f.start_ea
yield Characteristic("loop"), fh.address
def extract_recursive_call(f):
"""extract recursive function call
args:
f (IDA func_t)
"""
if capa.features.extractors.ida.helpers.is_function_recursive(f):
yield Characteristic("recursive call"), f.start_ea
def extract_recursive_call(fh: FunctionHandle):
"""extract recursive function call"""
if capa.features.extractors.ida.helpers.is_function_recursive(fh.inner):
yield Characteristic("recursive call"), fh.address
def extract_features(f):
"""extract function features
arg:
f (IDA func_t)
"""
def extract_features(fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
for func_handler in FUNCTION_HANDLERS:
for (feature, ea) in func_handler(f):
yield feature, ea
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 f in capa.features.extractors.ida.get_functions(skip_thunks=True, skip_libs=True):
features.extend(list(extract_features(f)))
import pprint
pprint.pprint(features)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,65 @@
# 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 typing import Tuple, Iterator
import idaapi
import ida_loader
import capa.ida.helpers
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]]:
format_name: str = ida_loader.get_file_type_name()
if "PE" in format_name:
yield OS(OS_WINDOWS), NO_ADDRESS
elif "ELF" in format_name:
with contextlib.closing(capa.ida.helpers.IDAIO()) 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
def extract_arch() -> Iterator[Tuple[Feature, Address]]:
info: idaapi.idainfo = idaapi.get_inf_structure()
if info.procname == "metapc" and info.is_64bit():
yield Arch(ARCH_AMD64), NO_ADDRESS
elif info.procname == "metapc" and info.is_32bit():
yield Arch(ARCH_I386), NO_ADDRESS
elif info.procname == "metapc":
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", info.procname)
return

View File

@@ -1,50 +1,58 @@
# Copyright (C) 2020 FireEye, 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 sys
import string
import functools
from typing import Any, Dict, Tuple, Iterator, Optional
import idc
import idaapi
import idautils
import ida_bytes
import ida_segment
from capa.features.address import AbsoluteVirtualAddress
from capa.features.extractors.base_extractor import FunctionHandle
def find_byte_sequence(start, end, seq):
"""find byte sequence
def find_byte_sequence(start: int, end: int, seq: bytes) -> Iterator[int]:
"""yield all ea of a given byte sequence
args:
start: min virtual address
end: max virtual address
seq: bytes to search e.g. b'\x01\x03'
seq: bytes to search e.g. b"\x01\x03"
"""
if sys.version_info[0] >= 3:
return idaapi.find_binary(start, end, " ".join(["%02x" % b for b in seq]), 0, idaapi.SEARCH_DOWN)
else:
return idaapi.find_binary(start, end, " ".join(["%02x" % ord(b) for b in seq]), 0, idaapi.SEARCH_DOWN)
seqstr = " ".join([f"{b:02x}" for b in seq])
while True:
# TODO(mike-hunhoff): find_binary is deprecated. Please use ida_bytes.bin_search() instead.
# https://github.com/mandiant/capa/issues/1606
ea = idaapi.find_binary(start, end, seqstr, 0, idaapi.SEARCH_DOWN)
if ea == idaapi.BADADDR:
break
start = ea + 1
yield ea
def get_functions(start=None, end=None, skip_thunks=False, skip_libs=False):
def get_functions(
start: Optional[int] = None, end: Optional[int] = None, skip_thunks: bool = False, skip_libs: bool = False
) -> Iterator[FunctionHandle]:
"""get functions, range optional
args:
start: min virtual address
end: max virtual address
ret:
yield func_t*
"""
for ea in idautils.Functions(start=start, end=end):
f = idaapi.get_func(ea)
if not (skip_thunks and (f.flags & idaapi.FUNC_THUNK) or skip_libs and (f.flags & idaapi.FUNC_LIB)):
yield f
yield FunctionHandle(address=AbsoluteVirtualAddress(ea), inner=f)
def get_segments(skip_header_segments=False):
def get_segments(skip_header_segments=False) -> Iterator[idaapi.segment_t]:
"""get list of segments (sections) in the binary image
args:
@@ -56,7 +64,7 @@ def get_segments(skip_header_segments=False):
yield seg
def get_segment_buffer(seg):
def get_segment_buffer(seg: idaapi.segment_t) -> bytes:
"""return bytes stored in a given segment
decrease buffer size until IDA is able to read bytes from the segment
@@ -74,9 +82,22 @@ def get_segment_buffer(seg):
return buff if buff else b""
def get_file_imports():
""" get file imports """
imports = {}
def inspect_import(imports, library, ea, function, ordinal):
if function and function.startswith("__imp_"):
# handle mangled PE imports
function = function[len("__imp_") :]
if function and "@@" in function:
# handle mangled ELF imports, like "fopen@@glibc_2.2.5"
function, _, _ = function.partition("@@")
imports[ea] = (library.lower(), function, ordinal)
return True
def get_file_imports() -> Dict[int, Tuple[str, str, int]]:
"""get file imports"""
imports: Dict[int, Tuple[str, str, int]] = {}
for idx in range(idaapi.get_import_module_qty()):
library = idaapi.get_import_module_name(idx)
@@ -84,26 +105,38 @@ def get_file_imports():
if not library:
continue
def inspect_import(ea, function, ordinal):
if function and function.startswith("__imp_"):
# handle mangled names starting
function = function[len("__imp_") :]
imports[ea] = (library.lower(), function, ordinal)
return True
# IDA uses section names for the library of ELF imports, like ".dynsym".
# These are not useful to us, we may need to expand this list over time
# TODO(williballenthin): find all section names used by IDA
# https://github.com/mandiant/capa/issues/1419
if library == ".dynsym":
library = ""
idaapi.enum_import_names(idx, inspect_import)
cb = functools.partial(inspect_import, imports, library)
idaapi.enum_import_names(idx, cb)
return imports
def get_instructions_in_range(start, end):
def get_file_externs() -> Dict[int, Tuple[str, str, int]]:
externs = {}
for seg in get_segments(skip_header_segments=True):
if seg.type != ida_segment.SEG_XTRN:
continue
for ea in idautils.Functions(seg.start_ea, seg.end_ea):
externs[ea] = ("", idaapi.get_func_name(ea), -1)
return externs
def get_instructions_in_range(start: int, end: int) -> Iterator[idaapi.insn_t]:
"""yield instructions in range
args:
start: virtual address (inclusive)
end: virtual address (exclusive)
yield:
(insn_t*)
"""
for head in idautils.Heads(start, end):
insn = idautils.DecodeInstruction(head)
@@ -111,8 +144,8 @@ def get_instructions_in_range(start, end):
yield insn
def is_operand_equal(op1, op2):
""" compare two IDA op_t """
def is_operand_equal(op1: idaapi.op_t, op2: idaapi.op_t) -> bool:
"""compare two IDA op_t"""
if op1.flags != op2.flags:
return False
@@ -137,8 +170,8 @@ def is_operand_equal(op1, op2):
return True
def is_basic_block_equal(bb1, bb2):
""" compare two IDA BasicBlock """
def is_basic_block_equal(bb1: idaapi.BasicBlock, bb2: idaapi.BasicBlock) -> bool:
"""compare two IDA BasicBlock"""
if bb1.start_ea != bb2.start_ea:
return False
@@ -151,13 +184,17 @@ def is_basic_block_equal(bb1, bb2):
return True
def basic_block_size(bb):
""" calculate size of basic block """
def basic_block_size(bb: idaapi.BasicBlock) -> int:
"""calculate size of basic block"""
return bb.end_ea - bb.start_ea
def read_bytes_at(ea, count):
def read_bytes_at(ea: int, count: int) -> bytes:
""" """
# check if byte has a value, see get_wide_byte doc
if not idc.is_loaded(ea):
return b""
segm_end = idc.get_segm_end(ea)
if ea + count > segm_end:
return idc.get_bytes(ea, segm_end - ea)
@@ -165,10 +202,10 @@ def read_bytes_at(ea, count):
return idc.get_bytes(ea, count)
def find_string_at(ea, min=4):
""" check if ASCII string exists at a given virtual address """
def find_string_at(ea: int, min_: int = 4) -> str:
"""check if ASCII string exists at a given virtual address"""
found = idaapi.get_strlit_contents(ea, -1, idaapi.STRTYPE_C)
if found and len(found) > min:
if found and len(found) >= min_:
try:
found = found.decode("ascii")
# hacky check for IDA bug; get_strlit_contents also reads Unicode as
@@ -182,7 +219,7 @@ def find_string_at(ea, min=4):
return ""
def get_op_phrase_info(op):
def get_op_phrase_info(op: idaapi.op_t) -> Dict:
"""parse phrase features from operand
Pretty much dup of sark's implementation:
@@ -192,7 +229,8 @@ def get_op_phrase_info(op):
return {}
scale = 1 << ((op.specflag2 & 0xC0) >> 6)
offset = op.addr
# IDA ea_t may be 32- or 64-bit; we assume displacement can only be 32-bit
offset = op.addr & 0xFFFFFFFF
if op.specflag1 == 0:
index = None
@@ -219,41 +257,45 @@ def get_op_phrase_info(op):
return {"base": base, "index": index, "scale": scale, "offset": offset}
def is_op_write(insn, op):
""" Check if an operand is written to (destination operand) """
def is_op_write(insn: idaapi.insn_t, op: idaapi.op_t) -> bool:
"""Check if an operand is written to (destination operand)"""
return idaapi.has_cf_chg(insn.get_canon_feature(), op.n)
def is_op_read(insn, op):
""" Check if an operand is read from (source operand) """
def is_op_read(insn: idaapi.insn_t, op: idaapi.op_t) -> bool:
"""Check if an operand is read from (source operand)"""
return idaapi.has_cf_use(insn.get_canon_feature(), op.n)
def is_sp_modified(insn):
""" determine if instruction modifies SP, ESP, RSP """
for op in get_insn_ops(insn, target_ops=(idaapi.o_reg,)):
if op.reg == idautils.procregs.sp.reg and is_op_write(insn, op):
# register is stack and written
return True
return False
def is_op_offset(insn: idaapi.insn_t, op: idaapi.op_t) -> bool:
"""Check is an operand has been marked as an offset (by auto-analysis or manually)"""
flags = idaapi.get_flags(insn.ea)
return ida_bytes.is_off(flags, op.n)
def is_bp_modified(insn):
""" check if instruction modifies BP, EBP, RBP """
for op in get_insn_ops(insn, target_ops=(idaapi.o_reg,)):
if op.reg == idautils.procregs.bp.reg and is_op_write(insn, op):
# register is base and written
return True
return False
def is_sp_modified(insn: idaapi.insn_t) -> bool:
"""determine if instruction modifies SP, ESP, RSP"""
return any(
op.reg == idautils.procregs.sp.reg and is_op_write(insn, op)
for op in get_insn_ops(insn, target_ops=(idaapi.o_reg,))
)
def is_frame_register(reg):
""" check if register is sp or bp """
def is_bp_modified(insn: idaapi.insn_t) -> bool:
"""check if instruction modifies BP, EBP, RBP"""
return any(
op.reg == idautils.procregs.bp.reg and is_op_write(insn, op)
for op in get_insn_ops(insn, target_ops=(idaapi.o_reg,))
)
def is_frame_register(reg: int) -> bool:
"""check if register is sp or bp"""
return reg in (idautils.procregs.sp.reg, idautils.procregs.bp.reg)
def get_insn_ops(insn, target_ops=()):
""" yield op_t for instruction, filter on type if specified """
def get_insn_ops(insn: idaapi.insn_t, target_ops: Optional[Tuple[Any]] = None) -> idaapi.op_t:
"""yield op_t for instruction, filter on type if specified"""
for op in insn.ops:
if op.type == idaapi.o_void:
# avoid looping all 6 ops if only subset exists
@@ -263,12 +305,12 @@ def get_insn_ops(insn, target_ops=()):
yield op
def is_op_stack_var(ea, index):
""" check if operand is a stack variable """
def is_op_stack_var(ea: int, index: int) -> bool:
"""check if operand is a stack variable"""
return idaapi.is_stkvar(idaapi.get_flags(ea), index)
def mask_op_val(op):
def mask_op_val(op: idaapi.op_t) -> int:
"""mask value by data type
necessary due to a bug in AMD64
@@ -288,26 +330,15 @@ def mask_op_val(op):
return masks.get(op.dtype, op.value) & op.value
def is_function_recursive(f):
"""check if function is recursive
args:
f (IDA func_t)
"""
for ref in idautils.CodeRefsTo(f.start_ea, True):
if f.contains(ref):
return True
return False
def is_function_recursive(f: idaapi.func_t) -> bool:
"""check if function is recursive"""
return any(f.contains(ref) for ref in idautils.CodeRefsTo(f.start_ea, True))
def is_basic_block_tight_loop(bb):
def is_basic_block_tight_loop(bb: idaapi.BasicBlock) -> bool:
"""check basic block loops to self
true if last instruction in basic block branches to basic block start
args:
f (IDA func_t)
bb (IDA BasicBlock)
"""
bb_end = idc.prev_head(bb.end_ea)
if bb.start_ea < bb_end:
@@ -317,8 +348,8 @@ def is_basic_block_tight_loop(bb):
return False
def find_data_reference_from_insn(insn, max_depth=10):
""" search for data reference from instruction, return address of instruction if no reference exists """
def find_data_reference_from_insn(insn: idaapi.insn_t, max_depth: int = 10) -> int:
"""search for data reference from instruction, return address of instruction if no reference exists"""
depth = 0
ea = insn.ea
@@ -333,6 +364,10 @@ def find_data_reference_from_insn(insn, max_depth=10):
# break if circular reference
break
if not idaapi.is_mapped(data_refs[0]):
# break if address is not mapped
break
depth += 1
if depth > max_depth:
# break if max depth
@@ -343,19 +378,17 @@ def find_data_reference_from_insn(insn, max_depth=10):
return ea
def get_function_blocks(f):
"""yield basic blocks contained in specified function
args:
f (IDA func_t)
yield:
block (IDA BasicBlock)
"""
def get_function_blocks(f: idaapi.func_t) -> Iterator[idaapi.BasicBlock]:
"""yield basic blocks contained in specified function"""
# leverage idaapi.FC_NOEXT flag to ignore useless external blocks referenced by the function
for block in idaapi.FlowChart(f, flags=(idaapi.FC_PREDS | idaapi.FC_NOEXT)):
yield block
yield from idaapi.FlowChart(f, flags=(idaapi.FC_PREDS | idaapi.FC_NOEXT))
def is_basic_block_return(bb):
""" check if basic block is return block """
def is_basic_block_return(bb: idaapi.BasicBlock) -> bool:
"""check if basic block is return block"""
return bb.type == idaapi.fcb_ret
def has_sib(oper: idaapi.op_t) -> bool:
# via: https://reverseengineering.stackexchange.com/a/14300
return oper.specflag1 == 1

View File

@@ -1,10 +1,11 @@
# Copyright (C) 2020 FireEye, 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
import idc
import idaapi
@@ -12,86 +13,112 @@ import idautils
import capa.features.extractors.helpers
import capa.features.extractors.ida.helpers
from capa.features import ARCH_X32, ARCH_X64, MAX_BYTES_FEATURE_SIZE, Bytes, String, Characteristic
from capa.features.insn import Number, Offset, Mnemonic
from capa.features.insn import API, MAX_STRUCTURE_SIZE, Number, Offset, Mnemonic, OperandNumber, OperandOffset
from capa.features.common import MAX_BYTES_FEATURE_SIZE, THUNK_CHAIN_DEPTH_DELTA, 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
def get_arch(ctx):
"""
fetch the ARCH_* constant for the currently open workspace.
via Tamir Bahar/@tmr232
https://reverseengineering.stackexchange.com/a/11398/17194
"""
if "arch" not in ctx:
info = idaapi.get_inf_structure()
if info.is_64bit():
ctx["arch"] = ARCH_X64
elif info.is_32bit():
ctx["arch"] = ARCH_X32
else:
raise ValueError("unexpected architecture")
return ctx["arch"]
def get_imports(ctx):
def get_imports(ctx: Dict[str, Any]) -> Dict[int, Any]:
if "imports_cache" not in ctx:
ctx["imports_cache"] = capa.features.extractors.ida.helpers.get_file_imports()
return ctx["imports_cache"]
def check_for_api_call(ctx, insn):
""" check instruction for API call """
if not idaapi.is_call_insn(insn):
return
def get_externs(ctx: Dict[str, Any]) -> Dict[int, Any]:
if "externs_cache" not in ctx:
ctx["externs_cache"] = capa.features.extractors.ida.helpers.get_file_externs()
return ctx["externs_cache"]
for ref in idautils.CodeRefsFrom(insn.ea, False):
info = get_imports(ctx).get(ref, ())
def check_for_api_call(insn: idaapi.insn_t, funcs: Dict[int, Any]) -> Iterator[Any]:
"""check instruction for API call"""
info = ()
ref = insn.ea
# attempt to resolve API calls by following chained thunks to a reasonable depth
for _ in range(THUNK_CHAIN_DEPTH_DELTA):
# assume only one code/data ref when resolving "call" or "jmp"
try:
ref = tuple(idautils.CodeRefsFrom(ref, False))[0]
except IndexError:
try:
# thunks may be marked as data refs
ref = tuple(idautils.DataRefsFrom(ref))[0]
except IndexError:
break
info = funcs.get(ref, ())
if info:
yield "%s.%s" % (info[0], info[1])
else:
f = idaapi.get_func(ref)
# check if call to thunk
# TODO: first instruction might not always be the thunk
if f and (f.flags & idaapi.FUNC_THUNK):
for thunk_ref in idautils.DataRefsFrom(ref):
# TODO: always data ref for thunk??
info = get_imports(ctx).get(thunk_ref, ())
if info:
yield "%s.%s" % (info[0], info[1])
break
f = idaapi.get_func(ref)
if not f or not (f.flags & idaapi.FUNC_THUNK):
break
if info:
yield info
def extract_insn_api_features(f, bb, insn):
"""parse instruction API features
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
def extract_insn_api_features(fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""
parse instruction API features
example:
call dword [0x00473038]
call dword [0x00473038]
"""
for api in check_for_api_call(f.ctx, insn):
for (feature, ea) in capa.features.extractors.helpers.generate_api_features(api, insn.ea):
yield feature, ea
insn: idaapi.insn_t = ih.inner
if insn.get_canon_mnem() not in ("call", "jmp"):
return
# check calls to imported functions
for api in check_for_api_call(insn, get_imports(fh.ctx)):
# tuple (<module>, <function>, <ordinal>)
for name in capa.features.extractors.helpers.generate_symbols(api[0], api[1]):
yield API(name), ih.address
# check calls to extern functions
for api in check_for_api_call(insn, get_externs(fh.ctx)):
# tuple (<module>, <function>, <ordinal>)
yield API(api[1]), ih.address
# extract IDA/FLIRT recognized API functions
targets = tuple(idautils.CodeRefsFrom(insn.ea, False))
if not targets:
return
target = targets[0]
target_func = idaapi.get_func(target)
if not target_func or target_func.start_ea != target:
# not a function (start)
return
if target_func.flags & idaapi.FUNC_LIB:
name = idaapi.get_name(target_func.start_ea)
yield API(name), ih.address
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 API(name[1:]), ih.address
def extract_insn_number_features(f, bb, insn):
"""parse instruction number features
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
def extract_insn_number_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
parse instruction number features
example:
push 3136B0h ; dwControlCode
"""
insn: idaapi.insn_t = ih.inner
if idaapi.is_ret_insn(insn):
# skip things like:
# .text:0042250E retn 8
@@ -102,68 +129,97 @@ def extract_insn_number_features(f, bb, insn):
# .text:00401145 add esp, 0Ch
return
for op in capa.features.extractors.ida.helpers.get_insn_ops(insn, target_ops=(idaapi.o_imm, idaapi.o_mem)):
for i, op in enumerate(insn.ops):
if op.type == idaapi.o_void:
break
if op.type not in (idaapi.o_imm, idaapi.o_mem):
continue
# skip things like:
# .text:00401100 shr eax, offset loc_C
if capa.features.extractors.ida.helpers.is_op_offset(insn, op):
continue
if op.type == idaapi.o_imm:
const = capa.features.extractors.ida.helpers.mask_op_val(op)
else:
const = op.addr
if not idaapi.is_mapped(const):
yield Number(const), insn.ea
yield Number(const, arch=get_arch(f.ctx)), insn.ea
yield Number(const), ih.address
yield OperandNumber(i, const), ih.address
if insn.itype == idaapi.NN_add and 0 < const < MAX_STRUCTURE_SIZE and op.type == idaapi.o_imm:
# for pattern like:
#
# add eax, 0x10
#
# assume 0x10 is also an offset (imagine eax is a pointer).
yield Offset(const), ih.address
yield OperandOffset(i, const), ih.address
def extract_insn_bytes_features(f, bb, insn):
"""parse referenced byte sequences
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
def extract_insn_bytes_features(fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""
parse referenced byte sequences
example:
push offset iid_004118d4_IShellLinkA ; riid
"""
insn: idaapi.insn_t = ih.inner
if idaapi.is_call_insn(insn):
return
ref = capa.features.extractors.ida.helpers.find_data_reference_from_insn(insn)
if ref != insn.ea:
extracted_bytes = capa.features.extractors.ida.helpers.read_bytes_at(ref, MAX_BYTES_FEATURE_SIZE)
if extracted_bytes and not capa.features.extractors.helpers.all_zeros(extracted_bytes):
yield Bytes(extracted_bytes), insn.ea
if not capa.features.extractors.ida.helpers.find_string_at(ref):
# don't extract byte features for obvious strings
yield Bytes(extracted_bytes), ih.address
def extract_insn_string_features(f, bb, insn):
"""parse instruction string features
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
def extract_insn_string_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
parse instruction string features
example:
push offset aAcr ; "ACR > "
"""
insn: idaapi.insn_t = ih.inner
ref = capa.features.extractors.ida.helpers.find_data_reference_from_insn(insn)
if ref != insn.ea:
found = capa.features.extractors.ida.helpers.find_string_at(ref)
if found:
yield String(found), insn.ea
yield String(found), ih.address
def extract_insn_offset_features(f, bb, insn):
"""parse instruction structure offset features
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
def extract_insn_offset_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
parse instruction structure offset features
example:
.text:0040112F cmp [esi+4], ebx
"""
for op in capa.features.extractors.ida.helpers.get_insn_ops(insn, target_ops=(idaapi.o_phrase, idaapi.o_displ)):
insn: idaapi.insn_t = ih.inner
for i, op in enumerate(insn.ops):
if op.type == idaapi.o_void:
break
if op.type not in (idaapi.o_phrase, idaapi.o_displ):
continue
if capa.features.extractors.ida.helpers.is_op_stack_var(insn.ea, op.n):
continue
p_info = capa.features.extractors.ida.helpers.get_op_phrase_info(op)
op_off = p_info.get("offset", 0)
op_off = p_info.get("offset")
if op_off is None:
continue
if idaapi.is_mapped(op_off):
# Ignore:
# mov esi, dword_1005B148[esi]
@@ -174,12 +230,32 @@ def extract_insn_offset_features(f, bb, insn):
# https://stackoverflow.com/questions/31853189/x86-64-assembly-why-displacement-not-64-bits
op_off = capa.features.extractors.helpers.twos_complement(op_off, 32)
yield Offset(op_off), insn.ea
yield Offset(op_off, arch=get_arch(f.ctx)), insn.ea
yield Offset(op_off), ih.address
yield OperandOffset(i, op_off), ih.address
if (
insn.itype == idaapi.NN_lea
and i == 1
# o_displ is used for both:
# [eax+1]
# [eax+ebx+2]
and op.type == idaapi.o_displ
# but the SIB is only present for [eax+ebx+2]
# which we don't want
and not capa.features.extractors.ida.helpers.has_sib(op)
):
# for pattern like:
#
# lea eax, [ebx + 1]
#
# assume 1 is also an offset (imagine ebx is a zero register).
yield Number(op_off), ih.address
yield OperandNumber(i, op_off), ih.address
def contains_stack_cookie_keywords(s):
"""check if string contains stack cookie keywords
def contains_stack_cookie_keywords(s: str) -> bool:
"""
check if string contains stack cookie keywords
Examples:
xor ecx, ebp ; StackCookie
@@ -193,7 +269,7 @@ def contains_stack_cookie_keywords(s):
return any(keyword in s for keyword in ("stack", "security"))
def bb_stack_cookie_registers(bb):
def bb_stack_cookie_registers(bb: idaapi.BasicBlock) -> Iterator[int]:
"""scan basic block for stack cookie operations
yield registers ids that may have been used for stack cookie operations
@@ -227,8 +303,8 @@ def bb_stack_cookie_registers(bb):
yield op.reg
def is_nzxor_stack_cookie_delta(f, bb, insn):
""" check if nzxor exists within stack cookie delta """
def is_nzxor_stack_cookie_delta(f: idaapi.func_t, bb: idaapi.BasicBlock, insn: idaapi.insn_t) -> bool:
"""check if nzxor exists within stack cookie delta"""
# security cookie check should use SP or BP
if not capa.features.extractors.ida.helpers.is_frame_register(insn.Op2.reg):
return False
@@ -250,8 +326,8 @@ def is_nzxor_stack_cookie_delta(f, bb, insn):
return False
def is_nzxor_stack_cookie(f, bb, insn):
""" check if nzxor is related to stack cookie """
def is_nzxor_stack_cookie(f: idaapi.func_t, bb: idaapi.BasicBlock, insn: idaapi.insn_t) -> bool:
"""check if nzxor is related to stack cookie"""
if contains_stack_cookie_keywords(idaapi.get_cmt(insn.ea, False)):
# Example:
# xor ecx, ebp ; StackCookie
@@ -267,37 +343,49 @@ def is_nzxor_stack_cookie(f, bb, insn):
return False
def extract_insn_nzxor_characteristic_features(f, bb, insn):
"""parse instruction non-zeroing XOR instruction
ignore expected non-zeroing XORs, e.g. security cookies
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
def extract_insn_nzxor_characteristic_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
if insn.itype != idaapi.NN_xor:
parse instruction non-zeroing XOR instruction
ignore expected non-zeroing XORs, e.g. security cookies
"""
insn: idaapi.insn_t = ih.inner
if insn.itype not in (idaapi.NN_xor, idaapi.NN_xorpd, idaapi.NN_xorps, idaapi.NN_pxor):
return
if capa.features.extractors.ida.helpers.is_operand_equal(insn.Op1, insn.Op2):
return
if is_nzxor_stack_cookie(f, bb, insn):
if is_nzxor_stack_cookie(fh.inner, bbh.inner, insn):
return
yield Characteristic("nzxor"), insn.ea
yield Characteristic("nzxor"), ih.address
def extract_insn_mnemonic_features(f, bb, insn):
"""parse instruction mnemonic features
def extract_insn_mnemonic_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction mnemonic features"""
yield Mnemonic(idc.print_insn_mnem(ih.inner.ea)), ih.address
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
def extract_insn_obfs_call_plus_5_characteristic_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""
yield Mnemonic(insn.get_canon_mnem()), insn.ea
parse call $+5 instruction from the given instruction.
"""
insn: idaapi.insn_t = ih.inner
if not idaapi.is_call_insn(insn):
return
if insn.ea + 5 == idc.get_operand_value(insn.ea, 0):
yield Characteristic("call $+5"), ih.address
def extract_insn_peb_access_characteristic_features(f, bb, insn):
def extract_insn_peb_access_characteristic_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction peb access
fs:[0x30] on x86, gs:[0x60] on x64
@@ -305,51 +393,61 @@ def extract_insn_peb_access_characteristic_features(f, bb, insn):
TODO:
IDA should be able to do this..
"""
insn: idaapi.insn_t = ih.inner
if insn.itype not in (idaapi.NN_push, idaapi.NN_mov):
return
if all(map(lambda op: op.type != idaapi.o_mem, insn.ops)):
if all(op.type != idaapi.o_mem for op in insn.ops):
# try to optimize for only memory references
return
disasm = idc.GetDisasm(insn.ea)
if " fs:30h" in disasm or " gs:60h" in disasm:
# TODO: replace above with proper IDA
yield Characteristic("peb access"), insn.ea
# TODO(mike-hunhoff): use proper IDA API for fetching segment access
# scanning the disassembly text is a hack.
# https://github.com/mandiant/capa/issues/1605
yield Characteristic("peb access"), ih.address
def extract_insn_segment_access_features(f, bb, insn):
def extract_insn_segment_access_features(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""parse instruction fs or gs access
TODO:
IDA should be able to do this...
"""
if all(map(lambda op: op.type != idaapi.o_mem, insn.ops)):
insn: idaapi.insn_t = ih.inner
if all(op.type != idaapi.o_mem for op in insn.ops):
# try to optimize for only memory references
return
disasm = idc.GetDisasm(insn.ea)
if " fs:" in disasm:
# TODO: replace above with proper IDA
yield Characteristic("fs access"), insn.ea
# TODO(mike-hunhoff): use proper IDA API for fetching segment access
# scanning the disassembly text is a hack.
# https://github.com/mandiant/capa/issues/1605
yield Characteristic("fs access"), ih.address
if " gs:" in disasm:
# TODO: replace above with proper IDA
yield Characteristic("gs access"), insn.ea
# TODO(mike-hunhoff): use proper IDA API for fetching segment access
# scanning the disassembly text is a hack.
# https://github.com/mandiant/capa/issues/1605
yield Characteristic("gs access"), ih.address
def extract_insn_cross_section_cflow(f, bb, insn):
"""inspect the instruction for a CALL or JMP that crosses section boundaries
def extract_insn_cross_section_cflow(
fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
"""inspect the instruction for a CALL or JMP that crosses section boundaries"""
insn: idaapi.insn_t = ih.inner
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
"""
for ref in idautils.CodeRefsFrom(insn.ea, False):
if ref in get_imports(f.ctx).keys():
if ref in get_imports(fh.ctx):
# ignore API calls
continue
if not idaapi.getseg(ref):
@@ -357,50 +455,40 @@ def extract_insn_cross_section_cflow(f, bb, insn):
continue
if idaapi.getseg(ref) == idaapi.getseg(insn.ea):
continue
yield Characteristic("cross section flow"), insn.ea
yield Characteristic("cross section flow"), ih.address
def extract_function_calls_from(f, bb, insn):
def extract_function_calls_from(fh: FunctionHandle, bbh: 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
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
"""
insn: idaapi.insn_t = ih.inner
if idaapi.is_call_insn(insn):
for ref in idautils.CodeRefsFrom(insn.ea, False):
yield Characteristic("calls from"), ref
yield Characteristic("calls from"), AbsoluteVirtualAddress(ref)
def extract_function_indirect_call_characteristic_features(f, bb, insn):
def extract_function_indirect_call_characteristic_features(
fh: FunctionHandle, bbh: 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
most relevant at the function or basic block scope;
however, its most efficient to extract at the instruction scope
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
"""
insn: idaapi.insn_t = ih.inner
if idaapi.is_call_insn(insn) and idc.get_operand_type(insn.ea, 0) in (idc.o_reg, idc.o_phrase, idc.o_displ):
yield Characteristic("indirect call"), insn.ea
yield Characteristic("indirect call"), ih.address
def extract_features(f, bb, insn):
"""extract instruction features
args:
f (IDA func_t)
bb (IDA BasicBlock)
insn (IDA insn_t)
"""
def extract_features(f: FunctionHandle, bbh: BBHandle, insn: InsnHandle) -> Iterator[Tuple[Feature, Address]]:
"""extract instruction features"""
for inst_handler in INSTRUCTION_HANDLERS:
for (feature, ea) in inst_handler(f, bb, insn):
for feature, ea in inst_handler(f, bbh, insn):
yield feature, ea
@@ -412,26 +500,10 @@ INSTRUCTION_HANDLERS = (
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():
""" """
features = []
for f in capa.features.extractors.ida.helpers.get_functions(skip_thunks=True, skip_libs=True):
for bb in idaapi.FlowChart(f, flags=idaapi.FC_PREDS):
for insn in capa.features.extractors.ida.helpers.get_instructions_in_range(bb.start_ea, bb.end_ea):
features.extend(list(extract_features(f, bb, insn)))
import pprint
pprint.pprint(features)
if __name__ == "__main__":
main()

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2020 FireEye, 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
@@ -6,7 +6,7 @@
# 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 networkx import nx
import networkx
from networkx.algorithms.components import strongly_connected_components
@@ -20,6 +20,6 @@ def has_loop(edges, threshold=2):
returns:
bool
"""
g = nx.DiGraph()
g = networkx.DiGraph()
g.add_edges_from(edges)
return any(len(comp) >= threshold for comp in strongly_connected_components(g))

View File

@@ -0,0 +1,170 @@
# 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 Dict, List, Tuple, Union
from dataclasses import dataclass
from typing_extensions import TypeAlias
from capa.features.common import Feature
from capa.features.address import NO_ADDRESS, Address, ThreadAddress, ProcessAddress, DynamicCallAddress
from capa.features.extractors.base_extractor import (
BBHandle,
CallHandle,
InsnHandle,
SampleHashes,
ThreadHandle,
ProcessHandle,
FunctionHandle,
StaticFeatureExtractor,
DynamicFeatureExtractor,
)
@dataclass
class InstructionFeatures:
features: List[Tuple[Address, Feature]]
@dataclass
class BasicBlockFeatures:
features: List[Tuple[Address, Feature]]
instructions: Dict[Address, InstructionFeatures]
@dataclass
class FunctionFeatures:
features: List[Tuple[Address, Feature]]
basic_blocks: Dict[Address, BasicBlockFeatures]
@dataclass
class NullStaticFeatureExtractor(StaticFeatureExtractor):
"""
An extractor that extracts some user-provided features.
This is useful for testing, as we can provide expected values and see if matching works.
"""
base_address: Address
sample_hashes: SampleHashes
global_features: List[Feature]
file_features: List[Tuple[Address, Feature]]
functions: Dict[Address, FunctionFeatures]
def get_base_address(self):
return self.base_address
def get_sample_hashes(self) -> SampleHashes:
return self.sample_hashes
def extract_global_features(self):
for feature in self.global_features:
yield feature, NO_ADDRESS
def extract_file_features(self):
for address, feature in self.file_features:
yield feature, address
def get_functions(self):
for address in sorted(self.functions.keys()):
yield FunctionHandle(address, None)
def extract_function_features(self, f):
for address, feature in self.functions[f.address].features:
yield feature, address
def get_basic_blocks(self, f):
for address in sorted(self.functions[f.address].basic_blocks.keys()):
yield BBHandle(address, None)
def extract_basic_block_features(self, f, bb):
for address, feature in self.functions[f.address].basic_blocks[bb.address].features:
yield feature, address
def get_instructions(self, f, bb):
for address in sorted(self.functions[f.address].basic_blocks[bb.address].instructions.keys()):
yield InsnHandle(address, None)
def extract_insn_features(self, f, bb, insn):
for address, feature in self.functions[f.address].basic_blocks[bb.address].instructions[insn.address].features:
yield feature, address
@dataclass
class CallFeatures:
name: str
features: List[Tuple[Address, Feature]]
@dataclass
class ThreadFeatures:
features: List[Tuple[Address, Feature]]
calls: Dict[Address, CallFeatures]
@dataclass
class ProcessFeatures:
features: List[Tuple[Address, Feature]]
threads: Dict[Address, ThreadFeatures]
name: str
@dataclass
class NullDynamicFeatureExtractor(DynamicFeatureExtractor):
base_address: Address
sample_hashes: SampleHashes
global_features: List[Feature]
file_features: List[Tuple[Address, Feature]]
processes: Dict[Address, ProcessFeatures]
def extract_global_features(self):
for feature in self.global_features:
yield feature, NO_ADDRESS
def get_sample_hashes(self) -> SampleHashes:
return self.sample_hashes
def extract_file_features(self):
for address, feature in self.file_features:
yield feature, address
def get_processes(self):
for address in sorted(self.processes.keys()):
assert isinstance(address, ProcessAddress)
yield ProcessHandle(address=address, inner={})
def extract_process_features(self, ph):
for addr, feature in self.processes[ph.address].features:
yield feature, addr
def get_process_name(self, ph) -> str:
return self.processes[ph.address].name
def get_threads(self, ph):
for address in sorted(self.processes[ph.address].threads.keys()):
assert isinstance(address, ThreadAddress)
yield ThreadHandle(address=address, inner={})
def extract_thread_features(self, ph, th):
for addr, feature in self.processes[ph.address].threads[th.address].features:
yield feature, addr
def get_calls(self, ph, th):
for address in sorted(self.processes[ph.address].threads[th.address].calls.keys()):
assert isinstance(address, DynamicCallAddress)
yield CallHandle(address=address, inner={})
def extract_call_features(self, ph, th, ch):
for address, feature in self.processes[ph.address].threads[th.address].calls[ch.address].features:
yield feature, address
def get_call_name(self, ph, th, ch) -> str:
return self.processes[ph.address].threads[th.address].calls[ch.address].name
NullFeatureExtractor: TypeAlias = Union[NullStaticFeatureExtractor, NullDynamicFeatureExtractor]

View File

@@ -0,0 +1,229 @@
# 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
from pathlib import Path
import pefile
import capa.features.common
import capa.features.extractors
import capa.features.extractors.common
import capa.features.extractors.helpers
import capa.features.extractors.strings
from capa.features.file import Export, Import, Section
from capa.features.common import OS, ARCH_I386, FORMAT_PE, ARCH_AMD64, OS_WINDOWS, Arch, Format, Characteristic
from capa.features.address import NO_ADDRESS, FileOffsetAddress, AbsoluteVirtualAddress
from capa.features.extractors.base_extractor import SampleHashes, StaticFeatureExtractor
logger = logging.getLogger(__name__)
def extract_file_embedded_pe(buf, **kwargs):
for offset, _ in capa.features.extractors.helpers.carve_pe(buf, 1):
yield Characteristic("embedded pe"), FileOffsetAddress(offset)
def extract_file_export_names(pe, **kwargs):
base_address = pe.OPTIONAL_HEADER.ImageBase
if hasattr(pe, "DIRECTORY_ENTRY_EXPORT"):
for export in pe.DIRECTORY_ENTRY_EXPORT.symbols:
if not export.name:
continue
try:
name = export.name.partition(b"\x00")[0].decode("ascii")
except UnicodeDecodeError:
continue
if export.forwarder is None:
va = base_address + export.address
yield Export(name), AbsoluteVirtualAddress(va)
else:
try:
forwarded_name = export.forwarder.partition(b"\x00")[0].decode("ascii")
except UnicodeDecodeError:
continue
forwarded_name = capa.features.extractors.helpers.reformat_forwarded_export_name(forwarded_name)
va = base_address + export.address
yield Export(forwarded_name), AbsoluteVirtualAddress(va)
yield Characteristic("forwarded export"), AbsoluteVirtualAddress(va)
def extract_file_import_names(pe, **kwargs):
"""
extract imported function names
1. imports by ordinal:
- modulename.#ordinal
2. imports by name, results in two features to support importname-only matching:
- modulename.importname
- importname
"""
if hasattr(pe, "DIRECTORY_ENTRY_IMPORT"):
for dll in pe.DIRECTORY_ENTRY_IMPORT:
try:
modname = dll.dll.partition(b"\x00")[0].decode("ascii")
except UnicodeDecodeError:
continue
# strip extension
modname = modname.rpartition(".")[0].lower()
for imp in dll.imports:
if imp.import_by_ordinal:
impname = f"#{imp.ordinal}"
else:
try:
impname = imp.name.partition(b"\x00")[0].decode("ascii")
except UnicodeDecodeError:
continue
for name in capa.features.extractors.helpers.generate_symbols(modname, impname, include_dll=True):
yield Import(name), AbsoluteVirtualAddress(imp.address)
def extract_file_section_names(pe, **kwargs):
base_address = pe.OPTIONAL_HEADER.ImageBase
for section in pe.sections:
try:
name = section.Name.partition(b"\x00")[0].decode("ascii")
except UnicodeDecodeError:
continue
yield Section(name), AbsoluteVirtualAddress(base_address + section.VirtualAddress)
def extract_file_strings(buf, **kwargs):
yield from capa.features.extractors.common.extract_file_strings(buf)
def extract_file_function_names(**kwargs):
"""
extract the names of statically-linked library functions.
"""
if False:
# using a `yield` here to force this to be a generator, not function.
yield NotImplementedError("pefile doesn't have library matching")
return
def extract_file_os(**kwargs):
# assuming PE -> Windows
# though i suppose they're also used by UEFI
yield OS(OS_WINDOWS), NO_ADDRESS
def extract_file_format(**kwargs):
yield Format(FORMAT_PE), NO_ADDRESS
def extract_file_arch(pe, **kwargs):
if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"]:
yield Arch(ARCH_I386), NO_ADDRESS
elif pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"]:
yield Arch(ARCH_AMD64), NO_ADDRESS
else:
logger.warning("unsupported architecture: %s", pefile.MACHINE_TYPE[pe.FILE_HEADER.Machine])
def extract_file_features(pe, buf):
"""
extract file features from given workspace
args:
pe (pefile.PE): the parsed PE
buf: the raw sample bytes
yields:
Tuple[Feature, VA]: a feature and its location.
"""
for file_handler in FILE_HANDLERS:
# file_handler: type: (pe, bytes) -> Iterable[Tuple[Feature, Address]]
for feature, va in file_handler(pe=pe, buf=buf): # type: ignore
yield feature, va
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 extract_global_features(pe, buf):
"""
extract global features from given workspace
args:
pe (pefile.PE): the parsed PE
buf: the raw sample bytes
yields:
Tuple[Feature, VA]: a feature and its location.
"""
for handler in GLOBAL_HANDLERS:
# file_handler: type: (pe, bytes) -> Iterable[Tuple[Feature, Address]]
for feature, va in handler(pe=pe, buf=buf): # type: ignore
yield feature, va
GLOBAL_HANDLERS = (
extract_file_os,
extract_file_arch,
)
class PefileFeatureExtractor(StaticFeatureExtractor):
def __init__(self, path: Path):
super().__init__(hashes=SampleHashes.from_bytes(path.read_bytes()))
self.path: Path = path
self.pe = pefile.PE(str(path))
def get_base_address(self):
return AbsoluteVirtualAddress(self.pe.OPTIONAL_HEADER.ImageBase)
def extract_global_features(self):
buf = Path(self.path).read_bytes()
yield from extract_global_features(self.pe, buf)
def extract_file_features(self):
buf = Path(self.path).read_bytes()
yield from extract_file_features(self.pe, buf)
def get_functions(self):
raise NotImplementedError("PefileFeatureExtract can only be used to extract file features")
def extract_function_features(self, f):
raise NotImplementedError("PefileFeatureExtract can only be used to extract file features")
def get_basic_blocks(self, f):
raise NotImplementedError("PefileFeatureExtract can only be used to extract file features")
def extract_basic_block_features(self, f, bb):
raise NotImplementedError("PefileFeatureExtract can only be used to extract file features")
def get_instructions(self, f, bb):
raise NotImplementedError("PefileFeatureExtract can only be used to extract file features")
def extract_insn_features(self, f, bb, insn):
raise NotImplementedError("PefileFeatureExtract can only be used to extract file features")
def is_library_function(self, va):
raise NotImplementedError("PefileFeatureExtract can only be used to extract file features")
def get_function_name(self, va):
raise NotImplementedError("PefileFeatureExtract can only be used to extract file features")

View File

@@ -1,6 +1,6 @@
# strings code from FLOSS, https://github.com/fireeye/flare-floss
# strings code from FLOSS, https://github.com/mandiant/flare-floss
#
# Copyright (C) 2020 FireEye, 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
@@ -9,6 +9,7 @@
# See the License for the specific language governing permissions and limitations under the License.
import re
import contextlib
from collections import namedtuple
ASCII_BYTE = r" !\"#\$%&\'\(\)\*\+,-\./0123456789:;<=>\?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\]\^_`abcdefghijklmnopqrstuvwxyz\{\|\}\\\~\t".encode(
@@ -81,24 +82,5 @@ def extract_unicode_strings(buf, n=4):
reg = b"((?:[%s]\x00){%d,})" % (ASCII_BYTE, n)
r = re.compile(reg)
for match in r.finditer(buf):
try:
with contextlib.suppress(UnicodeDecodeError):
yield String(match.group().decode("utf-16"), match.start())
except UnicodeDecodeError:
pass
def main():
import sys
with open(sys.argv[1], "rb") as f:
b = f.read()
for s in extract_ascii_strings(b):
print("0x{:x}: {:s}".format(s.offset, s.s))
for s in extract_unicode_strings(b):
print("0x{:x}: {:s}".format(s.offset, s.s))
if __name__ == "__main__":
main()

View File

@@ -1,85 +0,0 @@
# Copyright (C) 2020 FireEye, 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 types
import file
import insn
import function
import viv_utils
import basicblock
import capa.features.extractors
import capa.features.extractors.viv.file
import capa.features.extractors.viv.insn
import capa.features.extractors.viv.function
import capa.features.extractors.viv.basicblock
from capa.features.extractors import FeatureExtractor
__all__ = ["file", "function", "basicblock", "insn"]
def get_va(self):
try:
# vivisect type
return self.va
except AttributeError:
pass
raise TypeError()
def add_va_int_cast(o):
"""
dynamically add a cast-to-int (`__int__`) method to the given object
that returns the value of the `.va` property.
this bit of skullduggery lets use cast viv-utils objects as ints.
the correct way of doing this is to update viv-utils (or subclass the objects here).
"""
setattr(o, "__int__", types.MethodType(get_va, o, type(o)))
return o
class VivisectFeatureExtractor(FeatureExtractor):
def __init__(self, vw, path):
super(VivisectFeatureExtractor, self).__init__()
self.vw = vw
self.path = path
def get_base_address(self):
# assume there is only one file loaded into the vw
return list(self.vw.filemeta.values())[0]["imagebase"]
def extract_file_features(self):
for feature, va in capa.features.extractors.viv.file.extract_features(self.vw, self.path):
yield feature, va
def get_functions(self):
for va in sorted(self.vw.getFunctions()):
yield add_va_int_cast(viv_utils.Function(self.vw, va))
def extract_function_features(self, f):
for feature, va in capa.features.extractors.viv.function.extract_features(f):
yield feature, va
def get_basic_blocks(self, f):
for bb in f.basic_blocks:
yield add_va_int_cast(bb)
def extract_basic_block_features(self, f, bb):
for feature, va in capa.features.extractors.viv.basicblock.extract_features(f, bb):
yield feature, va
def get_instructions(self, f, bb):
for insn in bb.instructions:
yield add_va_int_cast(insn)
def extract_insn_features(self, f, bb, insn):
for feature, va in capa.features.extractors.viv.insn.extract_features(f, bb, insn):
yield feature, va

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2020 FireEye, 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
@@ -8,27 +8,30 @@
import string
import struct
from typing import Tuple, Iterator
import envi
import vivisect.const
import envi.archs.i386.disasm
from capa.features import Characteristic
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
from capa.features.extractors.base_extractor import BBHandle, FunctionHandle
def interface_extract_basic_block_XXX(f, bb):
def interface_extract_basic_block_XXX(f: FunctionHandle, bb: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""
parse features from the given basic block.
args:
f (viv_utils.Function): the function to process.
bb (viv_utils.BasicBlock): the basic block to process.
f: the function to process.
bb: the basic block to process.
yields:
(Feature, int): the feature and the address at which its found.
(Feature, Address): the feature and the address at which its found.
"""
yield NotImplementedError("feature"), NotImplementedError("virtual address")
raise NotImplementedError
def _bb_has_tight_loop(f, bb):
@@ -37,17 +40,17 @@ def _bb_has_tight_loop(f, bb):
"""
if len(bb.instructions) > 0:
for bva, bflags in bb.instructions[-1].getBranches():
if bflags & vivisect.envi.BR_COND:
if bflags & envi.BR_COND:
if bva == bb.va:
return True
return False
def extract_bb_tight_loop(f, bb):
""" check basic block for tight loop indicators """
if _bb_has_tight_loop(f, bb):
yield Characteristic("tight loop"), bb.va
def extract_bb_tight_loop(f: FunctionHandle, bb: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""check basic block for tight loop indicators"""
if _bb_has_tight_loop(f, bb.inner):
yield Characteristic("tight loop"), bb.address
def _bb_has_stackstring(f, bb):
@@ -67,13 +70,13 @@ def _bb_has_stackstring(f, bb):
return False
def extract_stackstring(f, bb):
""" check basic block for stackstring indicators """
if _bb_has_stackstring(f, bb):
yield Characteristic("stack string"), bb.va
def extract_stackstring(f: FunctionHandle, bb: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""check basic block for stackstring indicators"""
if _bb_has_stackstring(f, bb.inner):
yield Characteristic("stack string"), bb.address
def is_mov_imm_to_stack(instr):
def is_mov_imm_to_stack(instr: envi.archs.i386.disasm.i386Opcode) -> bool:
"""
Return if instruction moves immediate onto stack
"""
@@ -89,7 +92,6 @@ def is_mov_imm_to_stack(instr):
if not src.isImmed():
return False
# TODO what about 64-bit operands?
if not isinstance(dst, envi.archs.i386.disasm.i386SibOper) and not isinstance(
dst, envi.archs.i386.disasm.i386RegMemOper
):
@@ -105,7 +107,7 @@ def is_mov_imm_to_stack(instr):
return True
def get_printable_len(oper):
def get_printable_len(oper: envi.archs.i386.disasm.i386ImmOper) -> int:
"""
Return string length if all operand bytes are ascii or utf16-le printable
"""
@@ -117,23 +119,33 @@ def get_printable_len(oper):
chars = struct.pack("<I", oper.imm)
elif oper.tsize == 8:
chars = struct.pack("<Q", oper.imm)
else:
raise ValueError(f"unexpected oper.tsize: {oper.tsize}")
if is_printable_ascii(chars):
return oper.tsize
if is_printable_utf16le(chars):
elif is_printable_utf16le(chars):
return oper.tsize / 2
return 0
else:
return 0
def is_printable_ascii(chars):
return all(ord(c) < 127 and c in string.printable for c in chars)
def is_printable_ascii(chars: bytes) -> bool:
try:
chars_str = chars.decode("ascii")
except UnicodeDecodeError:
return False
else:
return all(c in string.printable for c in chars_str)
def is_printable_utf16le(chars):
if all(c == "\x00" for c in chars[1::2]):
def is_printable_utf16le(chars: bytes) -> bool:
if all(c == 0x0 for c in chars[1::2]):
return is_printable_ascii(chars[::2])
return False
def extract_features(f, bb):
def extract_features(f: FunctionHandle, bb: BBHandle) -> Iterator[Tuple[Feature, Address]]:
"""
extract features from the given basic block.
@@ -142,12 +154,12 @@ def extract_features(f, bb):
bb (viv_utils.BasicBlock): the basic block to process.
yields:
Feature, set[VA]: the features and their location found in this basic block.
Tuple[Feature, int]: the features and their location found in this basic block.
"""
yield BasicBlock(), bb.va
yield BasicBlock(), AbsoluteVirtualAddress(bb.inner.va)
for bb_handler in BASIC_BLOCK_HANDLERS:
for feature, va in bb_handler(f, bb):
yield feature, va
for feature, addr in bb_handler(f, bb):
yield feature, addr
BASIC_BLOCK_HANDLERS = (

View File

@@ -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.
import logging
from typing import Any, Dict, List, Tuple, Iterator
from pathlib import Path
import viv_utils
import viv_utils.flirt
import capa.features.extractors.common
import capa.features.extractors.viv.file
import capa.features.extractors.viv.insn
import capa.features.extractors.viv.global_
import capa.features.extractors.viv.function
import capa.features.extractors.viv.basicblock
from capa.features.common import Feature
from capa.features.address import Address, AbsoluteVirtualAddress
from capa.features.extractors.base_extractor import (
BBHandle,
InsnHandle,
SampleHashes,
FunctionHandle,
StaticFeatureExtractor,
)
logger = logging.getLogger(__name__)
class VivisectFeatureExtractor(StaticFeatureExtractor):
def __init__(self, vw, path: Path, os):
self.vw = vw
self.path = path
self.buf = path.read_bytes()
super().__init__(hashes=SampleHashes.from_bytes(self.buf))
# pre-compute these because we'll yield them at *every* scope.
self.global_features: List[Tuple[Feature, Address]] = []
self.global_features.extend(capa.features.extractors.viv.file.extract_file_format(self.buf))
self.global_features.extend(capa.features.extractors.common.extract_os(self.buf, os))
self.global_features.extend(capa.features.extractors.viv.global_.extract_arch(self.vw))
def get_base_address(self):
# assume there is only one file loaded into the vw
return AbsoluteVirtualAddress(list(self.vw.filemeta.values())[0]["imagebase"])
def extract_global_features(self):
yield from self.global_features
def extract_file_features(self):
yield from capa.features.extractors.viv.file.extract_features(self.vw, self.buf)
def get_functions(self) -> Iterator[FunctionHandle]:
cache: Dict[str, Any] = {}
for va in sorted(self.vw.getFunctions()):
yield FunctionHandle(
address=AbsoluteVirtualAddress(va), inner=viv_utils.Function(self.vw, va), ctx={"cache": cache}
)
def extract_function_features(self, fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.viv.function.extract_features(fh)
def get_basic_blocks(self, fh: FunctionHandle) -> Iterator[BBHandle]:
f: viv_utils.Function = fh.inner
for bb in f.basic_blocks:
yield BBHandle(address=AbsoluteVirtualAddress(bb.va), inner=bb)
def extract_basic_block_features(self, fh: FunctionHandle, bbh) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.viv.basicblock.extract_features(fh, bbh)
def get_instructions(self, fh: FunctionHandle, bbh: BBHandle) -> Iterator[InsnHandle]:
bb: viv_utils.BasicBlock = bbh.inner
for insn in bb.instructions:
yield InsnHandle(address=AbsoluteVirtualAddress(insn.va), inner=insn)
def extract_insn_features(
self, fh: FunctionHandle, bbh: BBHandle, ih: InsnHandle
) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.viv.insn.extract_features(fh, bbh, ih)
def is_library_function(self, addr):
return viv_utils.flirt.is_library_function(self.vw, addr)
def get_function_name(self, addr):
return viv_utils.get_function_name(self.vw, addr)

View File

@@ -1,32 +1,62 @@
# Copyright (C) 2020 FireEye, 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 Tuple, Iterator
import PE.carve as pe_carve # vivisect PE
import vivisect
import viv_utils
import viv_utils.flirt
import capa.features.insn
import capa.features.extractors.common
import capa.features.extractors.helpers
import capa.features.extractors.strings
from capa.features import String, Characteristic
from capa.features.file import Export, Import, Section
from capa.features.file import Export, Import, Section, FunctionName
from capa.features.common import Feature, Characteristic
from capa.features.address import Address, FileOffsetAddress, AbsoluteVirtualAddress
def extract_file_embedded_pe(vw, file_path):
with open(file_path, "rb") as f:
fbytes = f.read()
for offset, i in pe_carve.carve(fbytes, 1):
yield Characteristic("embedded pe"), offset
def extract_file_embedded_pe(buf, **kwargs) -> Iterator[Tuple[Feature, Address]]:
for offset, _ in pe_carve.carve(buf, 1):
yield Characteristic("embedded pe"), FileOffsetAddress(offset)
def extract_file_export_names(vw, file_path):
for va, etype, name, _ in vw.getExports():
yield Export(name), va
def get_first_vw_filename(vw: vivisect.VivWorkspace):
# vivisect associates metadata with each file that its loaded into the workspace.
# capa only loads a single file into each workspace.
# so to access the metadata for the file in question, we can just take the first one.
# otherwise, we'd have to pass around the module name of the file we're analyzing,
# which is a pain.
#
# so this is a simplifying assumption.
return next(iter(vw.filemeta.keys()))
def extract_file_import_names(vw, file_path):
def extract_file_export_names(vw: vivisect.VivWorkspace, **kwargs) -> Iterator[Tuple[Feature, Address]]:
for va, _, name, _ in vw.getExports():
yield Export(name), AbsoluteVirtualAddress(va)
if vw.getMeta("Format") == "pe":
pe = vw.parsedbin
baseaddr = pe.IMAGE_NT_HEADERS.OptionalHeader.ImageBase
for rva, _, forwarded_name in vw.getFileMeta(get_first_vw_filename(vw), "forwarders"):
try:
forwarded_name = forwarded_name.partition(b"\x00")[0].decode("ascii")
except UnicodeDecodeError:
continue
forwarded_name = capa.features.extractors.helpers.reformat_forwarded_export_name(forwarded_name)
va = baseaddr + rva
yield Export(forwarded_name), AbsoluteVirtualAddress(va)
yield Characteristic("forwarded export"), AbsoluteVirtualAddress(va)
def extract_file_import_names(vw, **kwargs) -> Iterator[Tuple[Feature, Address]]:
"""
extract imported function names
1. imports by ordinal:
@@ -37,18 +67,17 @@ def extract_file_import_names(vw, file_path):
"""
for va, _, _, tinfo in vw.getImports():
# vivisect source: tinfo = "%s.%s" % (libname, impname)
modname, impname = tinfo.split(".")
modname, impname = tinfo.split(".", 1)
if is_viv_ord_impname(impname):
# replace ord prefix with #
impname = "#%s" % impname[len("ord") :]
tinfo = "%s.%s" % (modname, impname)
yield Import(tinfo), va
else:
yield Import(tinfo), va
yield Import(impname), va
impname = "#" + impname[len("ord") :]
addr = AbsoluteVirtualAddress(va)
for name in capa.features.extractors.helpers.generate_symbols(modname, impname, include_dll=True):
yield Import(name), addr
def is_viv_ord_impname(impname):
def is_viv_ord_impname(impname: str) -> bool:
"""
return if import name matches vivisect's ordinal naming scheme `'ord%d' % ord`
"""
@@ -62,40 +91,51 @@ def is_viv_ord_impname(impname):
return True
def extract_file_section_names(vw, file_path):
def extract_file_section_names(vw, **kwargs) -> Iterator[Tuple[Feature, Address]]:
for va, _, segname, _ in vw.getSegments():
yield Section(segname), va
yield Section(segname), AbsoluteVirtualAddress(va)
def extract_file_strings(vw, file_path):
def extract_file_strings(buf, **kwargs) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.common.extract_file_strings(buf)
def extract_file_function_names(vw, **kwargs) -> Iterator[Tuple[Feature, Address]]:
"""
extract ASCII and UTF-16 LE strings from file
extract the names of statically-linked library functions.
"""
with open(file_path, "rb") as f:
b = f.read()
for s in capa.features.extractors.strings.extract_ascii_strings(b):
yield String(s.s), s.offset
for s in capa.features.extractors.strings.extract_unicode_strings(b):
yield String(s.s), s.offset
for va in sorted(vw.getFunctions()):
addr = AbsoluteVirtualAddress(va)
if viv_utils.flirt.is_library_function(vw, va):
name = viv_utils.get_function_name(vw, va)
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_features(vw, file_path):
def extract_file_format(buf, **kwargs) -> Iterator[Tuple[Feature, Address]]:
yield from capa.features.extractors.common.extract_format(buf)
def extract_features(vw, buf: bytes) -> Iterator[Tuple[Feature, Address]]:
"""
extract file features from given workspace
args:
vw (vivisect.VivWorkspace): the vivisect workspace
file_path: path to the input file
buf: the raw input file bytes
yields:
Tuple[Feature, VA]: a feature and its location.
Tuple[Feature, Address]: a feature and its location.
"""
for file_handler in FILE_HANDLERS:
for feature, va in file_handler(vw, file_path):
yield feature, va
for feature, addr in file_handler(vw=vw, buf=buf): # type: ignore
yield feature, addr
FILE_HANDLERS = (
@@ -104,4 +144,6 @@ FILE_HANDLERS = (
extract_file_import_names,
extract_file_section_names,
extract_file_strings,
extract_file_function_names,
extract_file_format,
)

View File

@@ -1,70 +1,110 @@
# Copyright (C) 2020 FireEye, 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 Tuple, Iterator
import envi
import viv_utils
import vivisect.const
from capa.features import Characteristic
from capa.features.file import FunctionName
from capa.features.common import Feature, Characteristic
from capa.features.address import Address, AbsoluteVirtualAddress
from capa.features.extractors import loops
from capa.features.extractors.elf import SymTab
from capa.features.extractors.base_extractor import FunctionHandle
def interface_extract_function_XXX(f):
def interface_extract_function_XXX(fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
"""
parse features from the given function.
args:
f (viv_utils.Function): the function to process.
f: the function to process.
yields:
(Feature, int): the feature and the address at which its found.
(Feature, Address): the feature and the address at which its found.
"""
yield NotImplementedError("feature"), NotImplementedError("virtual address")
raise NotImplementedError
def extract_function_calls_to(f):
def extract_function_symtab_names(fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
if fh.inner.vw.metadata["Format"] == "elf":
# the file's symbol table gets added to the metadata of the vivisect workspace.
# this is in order to eliminate the computational overhead of refetching symtab each time.
if "symtab" not in fh.ctx["cache"]:
try:
fh.ctx["cache"]["symtab"] = SymTab.from_viv(fh.inner.vw.parsedbin)
except Exception:
fh.ctx["cache"]["symtab"] = None
symtab = fh.ctx["cache"]["symtab"]
if symtab:
for symbol in symtab.get_symbols():
sym_name = symtab.get_name(symbol)
sym_value = symbol.value
sym_info = symbol.info
STT_FUNC = 0x2
if sym_value == fh.address and sym_info & STT_FUNC != 0:
yield FunctionName(sym_name), fh.address
def extract_function_calls_to(fhandle: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
f: viv_utils.Function = fhandle.inner
for src, _, _, _ in f.vw.getXrefsTo(f.va, rtype=vivisect.const.REF_CODE):
yield Characteristic("calls to"), src
yield Characteristic("calls to"), AbsoluteVirtualAddress(src)
def extract_function_loop(f):
def extract_function_loop(fhandle: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
"""
parse if a function has a loop
"""
f: viv_utils.Function = fhandle.inner
edges = []
for bb in f.basic_blocks:
if len(bb.instructions) > 0:
for bva, bflags in bb.instructions[-1].getBranches():
if bva is None:
# vivisect may be unable to recover the call target, e.g. on dynamic calls like `call esi`
# for this bva is None, and we don't want to add it for loop detection, ref: vivisect#574
continue
# vivisect does not set branch flags for non-conditional jmp so add explicit check
if (
bflags & vivisect.envi.BR_COND
or bflags & vivisect.envi.BR_FALL
or bflags & vivisect.envi.BR_TABLE
bflags & envi.BR_COND
or bflags & envi.BR_FALL
or bflags & envi.BR_TABLE
or bb.instructions[-1].mnem == "jmp"
):
edges.append((bb.va, bva))
if edges and loops.has_loop(edges):
yield Characteristic("loop"), f.va
yield Characteristic("loop"), fhandle.address
def extract_features(f):
def extract_features(fh: FunctionHandle) -> Iterator[Tuple[Feature, Address]]:
"""
extract features from the given function.
args:
f (viv_utils.Function): the function from which to extract features
fh: the function handle from which to extract features
yields:
Feature, set[VA]: the features and their location found in this function.
Tuple[Feature, int]: the features and their location found in this function.
"""
for func_handler in FUNCTION_HANDLERS:
for feature, va in func_handler(f):
yield feature, va
for feature, addr in func_handler(fh):
yield feature, addr
FUNCTION_HANDLERS = (extract_function_calls_to, extract_function_loop)
FUNCTION_HANDLERS = (
extract_function_symtab_names,
extract_function_calls_to,
extract_function_loop,
)

Some files were not shown because too many files have changed in this diff Show More