Merge branch 'master' into idalib-tests

This commit is contained in:
Moritz
2025-11-24 19:52:40 +01:00
committed by GitHub
20 changed files with 205 additions and 55 deletions

View File

@@ -1,5 +1,5 @@
[tool.bumpversion] [tool.bumpversion]
current_version = "9.2.1" current_version = "9.3.1"
[[tool.bumpversion.files]] [[tool.bumpversion.files]]
filename = "capa/version.py" filename = "capa/version.py"
@@ -19,4 +19,9 @@ replace = '"flare-capa=={new_version}"'
[[tool.bumpversion.files]] [[tool.bumpversion.files]]
filename = "CHANGELOG.md" filename = "CHANGELOG.md"
search = "v{current_version}...master" search = "v{current_version}...master"
replace = "{current_version}...{new_version}" replace = "v{current_version}...{new_version}"
[[tool.bumpversion.files]]
filename = "CHANGELOG.md"
search = "master (unreleased)"
replace = "v{new_version}"

1
.gitignore vendored
View File

@@ -122,6 +122,7 @@ scripts/perf/*.zip
*/.DS_Store */.DS_Store
Pipfile Pipfile
Pipfile.lock Pipfile.lock
uv.lock
/cache/ /cache/
.github/binja/binaryninja .github/binja/binaryninja
.github/binja/download_headless.py .github/binja/download_headless.py

View File

@@ -3,12 +3,55 @@
## master (unreleased) ## master (unreleased)
### New Features ### New Features
### Breaking Changes
### New Rules (0)
-
### Bug Fixes
### capa Explorer Web
### capa Explorer IDA Pro plugin
### Development
### Raw diffs
- [capa v9.3.1...master](https://github.com/mandiant/capa/compare/v9.3.1...master)
- [capa-rules v9.3.1...master](https://github.com/mandiant/capa-rules/compare/v9.3.1...master)
## v9.3.1
This patch release fixes a missing import for the capa explorer plugin for IDA Pro.
### Bug Fixes
- add missing ida-netnode dependency to project.toml @mike-hunhoff #2765
### Development
- ci: bump binja min version @mike-hunhoff #2763
### Raw diffs
- [capa v9.3.0...master](https://github.com/mandiant/capa/compare/v9.3.0...master)
- [capa-rules v9.3.0...master](https://github.com/mandiant/capa-rules/compare/v9.3.0...master)
## v9.3.0
capa v9.3.0 comes with over 20 new and/or impoved rules.
For IDA users the capa explorer plugin is now available via the IDA Pro plugin repository and contains Qt compatibility layer for PyQt5 and PySide6 support.
Additionally a Binary Ninja bug has been fixed. Released binaries now include ARM64 binaries (Linux and macOS).
### New Features
- ci: add support for arm64 binary releases - ci: add support for arm64 binary releases
- tests: run tests against IDA via idalib @williballenthin #2742 - tests: run tests against IDA via idalib @williballenthin #2742
### Breaking Changes ### Breaking Changes
### New Rules (21) ### New Rules (24)
- anti-analysis/anti-vm/vm-detection/detect-mouse-movement-via-activity-checks-on-windows tevajdr@gmail.com - anti-analysis/anti-vm/vm-detection/detect-mouse-movement-via-activity-checks-on-windows tevajdr@gmail.com
- nursery/create-executable-heap moritz.raabe@mandiant.com - nursery/create-executable-heap moritz.raabe@mandiant.com
@@ -30,7 +73,9 @@
- host-interaction/network/routing-table/get-routing-table michael.hunhoff@mandiant.com - host-interaction/network/routing-table/get-routing-table michael.hunhoff@mandiant.com
- host-interaction/file-system/use-io_uring-io-interface-on-linux jakubjozwiak@google.com - host-interaction/file-system/use-io_uring-io-interface-on-linux jakubjozwiak@google.com
- collection/keylog/log-keystrokes-via-direct-input zeze-zeze - collection/keylog/log-keystrokes-via-direct-input zeze-zeze
- - nursery/compiled-from-fsharp mehunhoff@google.com
- nursery/decrypt-data-using-aes-via-dotnet mehunhoff@google.com
- nursery/get-dotnet-assembly-entry-point mehunhoff@google.com
### Bug Fixes ### Bug Fixes
@@ -41,6 +86,8 @@
### capa Explorer IDA Pro plugin ### capa Explorer IDA Pro plugin
- add `ida-plugin.json` for inclusion in the IDA Pro plugin repository @williballenthin - add `ida-plugin.json` for inclusion in the IDA Pro plugin repository @williballenthin
- ida plugin: add Qt compatibility layer for PyQt5 and PySide6 support @williballenthin #2707
- delay import to not load Qt* when running under idalib @mr-tz #2752
### Development ### Development
@@ -48,8 +95,8 @@
- dev: add bumpmyversion to bump and sync versions across the project @mr-tz - dev: add bumpmyversion to bump and sync versions across the project @mr-tz
### Raw diffs ### Raw diffs
- [capa v9.2.1...master](https://github.com/mandiant/capa/compare/v9.2.1...master) - [capa v9.2.1...9.3.0](https://github.com/mandiant/capa/compare/v9.2.1...9.3.0)
- [capa-rules v9.2.1...master](https://github.com/mandiant/capa-rules/compare/v9.2.1...master) - [capa-rules v9.2.1...9.3.0](https://github.com/mandiant/capa-rules/compare/v9.2.1...9.3.0)
## v9.2.1 ## v9.2.1

View File

@@ -315,3 +315,6 @@ If you use Ghidra, then you can use the [capa + Ghidra integration](/capa/ghidra
## capa testfiles ## capa testfiles
The [capa-testfiles repository](https://github.com/mandiant/capa-testfiles) contains the data we use to test capa's code and rules The [capa-testfiles repository](https://github.com/mandiant/capa-testfiles) contains the data we use to test capa's code and rules
## mailing list
Subscribe to the FLARE mailing list for community announcements! Email "subscribe" to [flare-external@google.com](mailto:flare-external@google.com?subject=subscribe).

View File

@@ -17,7 +17,6 @@ import logging
import idaapi import idaapi
import ida_kernwin import ida_kernwin
from capa.ida.plugin.form import CapaExplorerForm
from capa.ida.plugin.icon import ICON from capa.ida.plugin.icon import ICON
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -74,6 +73,9 @@ class CapaExplorerPlugin(idaapi.plugin_t):
arg (int): bitflag. Setting LSB enables automatic analysis upon arg (int): bitflag. Setting LSB enables automatic analysis upon
loading. The other bits are currently undefined. See `form.Options`. loading. The other bits are currently undefined. See `form.Options`.
""" """
# delay import to not trigger load of Qt components when not running in idaq, i.e., in idalib
from capa.ida.plugin.form import CapaExplorerForm
if not self.form: if not self.form:
self.form = CapaExplorerForm(self.PLUGIN_NAME, arg) self.form = CapaExplorerForm(self.PLUGIN_NAME, arg)
else: else:

View File

@@ -14,9 +14,9 @@
import ida_kernwin import ida_kernwin
from PyQt5 import QtCore
from capa.ida.plugin.error import UserCancelledError from capa.ida.plugin.error import UserCancelledError
from capa.ida.plugin.qt_compat import QtCore, Signal
from capa.features.extractors.ida.extractor import IdaFeatureExtractor from capa.features.extractors.ida.extractor import IdaFeatureExtractor
from capa.features.extractors.base_extractor import FunctionHandle from capa.features.extractors.base_extractor import FunctionHandle
@@ -24,7 +24,7 @@ from capa.features.extractors.base_extractor import FunctionHandle
class CapaExplorerProgressIndicator(QtCore.QObject): class CapaExplorerProgressIndicator(QtCore.QObject):
"""implement progress signal, used during feature extraction""" """implement progress signal, used during feature extraction"""
progress = QtCore.pyqtSignal(str) progress = Signal(str)
def update(self, text): def update(self, text):
"""emit progress update """emit progress update

View File

@@ -23,7 +23,6 @@ from pathlib import Path
import idaapi import idaapi
import ida_kernwin import ida_kernwin
import ida_settings import ida_settings
from PyQt5 import QtGui, QtCore, QtWidgets
import capa.main import capa.main
import capa.rules import capa.rules
@@ -51,6 +50,7 @@ from capa.ida.plugin.hooks import CapaExplorerIdaHooks
from capa.ida.plugin.model import CapaExplorerDataModel from capa.ida.plugin.model import CapaExplorerDataModel
from capa.ida.plugin.proxy import CapaExplorerRangeProxyModel, CapaExplorerSearchProxyModel from capa.ida.plugin.proxy import CapaExplorerRangeProxyModel, CapaExplorerSearchProxyModel
from capa.ida.plugin.extractor import CapaExplorerFeatureExtractor from capa.ida.plugin.extractor import CapaExplorerFeatureExtractor
from capa.ida.plugin.qt_compat import QtGui, QtCore, QtWidgets
from capa.features.extractors.base_extractor import FunctionHandle from capa.features.extractors.base_extractor import FunctionHandle
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -1358,7 +1358,7 @@ class CapaExplorerForm(idaapi.PluginForm):
@param state: checked state @param state: checked state
""" """
if state == QtCore.Qt.Checked: if state:
self.limit_results_to_function(idaapi.get_func(idaapi.get_screen_ea())) self.limit_results_to_function(idaapi.get_func(idaapi.get_screen_ea()))
else: else:
self.range_model_proxy.reset_address_range_filter() self.range_model_proxy.reset_address_range_filter()
@@ -1367,7 +1367,7 @@ class CapaExplorerForm(idaapi.PluginForm):
def slot_checkbox_limit_features_by_ea(self, state): def slot_checkbox_limit_features_by_ea(self, state):
""" """ """ """
if state == QtCore.Qt.Checked: if state:
self.view_rulegen_features.filter_items_by_ea(idaapi.get_screen_ea()) self.view_rulegen_features.filter_items_by_ea(idaapi.get_screen_ea())
else: else:
self.view_rulegen_features.show_all_items() self.view_rulegen_features.show_all_items()

View File

@@ -3,7 +3,7 @@
"plugin": { "plugin": {
"name": "capa", "name": "capa",
"entryPoint": "capa_explorer.py", "entryPoint": "capa_explorer.py",
"version": "9.2.1", "version": "9.3.1",
"idaVersions": ">=7.4", "idaVersions": ">=7.4",
"description": "Identify capabilities in executable files using FLARE's capa framework", "description": "Identify capabilities in executable files using FLARE's capa framework",
"license": "Apache-2.0", "license": "Apache-2.0",
@@ -12,7 +12,7 @@
"api-scripting-and-automation", "api-scripting-and-automation",
"ui-ux-and-visualization" "ui-ux-and-visualization"
], ],
"pythonDependencies": ["flare-capa==9.2.1"], "pythonDependencies": ["flare-capa==9.3.1"],
"urls": { "urls": {
"repository": "https://github.com/mandiant/capa" "repository": "https://github.com/mandiant/capa"
}, },

View File

@@ -18,10 +18,10 @@ from typing import Iterator, Optional
import idc import idc
import idaapi import idaapi
from PyQt5 import QtCore
import capa.ida.helpers import capa.ida.helpers
from capa.features.address import Address, FileOffsetAddress, AbsoluteVirtualAddress from capa.features.address import Address, FileOffsetAddress, AbsoluteVirtualAddress
from capa.ida.plugin.qt_compat import QtCore, qt_get_item_flag_tristate
def info_to_name(display): def info_to_name(display):
@@ -55,7 +55,7 @@ class CapaExplorerDataItem:
self.flags = QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable self.flags = QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
if self._can_check: if self._can_check:
self.flags = self.flags | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsTristate self.flags = self.flags | QtCore.Qt.ItemIsUserCheckable | qt_get_item_flag_tristate()
if self.pred: if self.pred:
self.pred.appendChild(self) self.pred.appendChild(self)

View File

@@ -18,7 +18,6 @@ from collections import deque
import idc import idc
import idaapi import idaapi
from PyQt5 import QtGui, QtCore
import capa.rules import capa.rules
import capa.ida.helpers import capa.ida.helpers
@@ -42,6 +41,7 @@ from capa.ida.plugin.item import (
CapaExplorerInstructionViewItem, CapaExplorerInstructionViewItem,
) )
from capa.features.address import Address, AbsoluteVirtualAddress from capa.features.address import Address, AbsoluteVirtualAddress
from capa.ida.plugin.qt_compat import QtGui, QtCore
# default highlight color used in IDA window # default highlight color used in IDA window
DEFAULT_HIGHLIGHT = 0xE6C700 DEFAULT_HIGHLIGHT = 0xE6C700
@@ -269,7 +269,7 @@ class CapaExplorerDataModel(QtCore.QAbstractItemModel):
visited.add(child_index) visited.add(child_index)
for idx in range(self.rowCount(child_index)): for idx in range(self.rowCount(child_index)):
stack.append(child_index.child(idx, 0)) stack.append(self.index(idx, 0, child_index))
def reset_ida_highlighting(self, item, checked): def reset_ida_highlighting(self, item, checked):
"""reset IDA highlight for item """reset IDA highlight for item

View File

@@ -12,10 +12,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
from capa.ida.plugin.model import CapaExplorerDataModel from capa.ida.plugin.model import CapaExplorerDataModel
from capa.ida.plugin.qt_compat import Qt, QtCore
class CapaExplorerRangeProxyModel(QtCore.QSortFilterProxyModel): class CapaExplorerRangeProxyModel(QtCore.QSortFilterProxyModel):

View File

@@ -0,0 +1,79 @@
# Copyright 2020 Google LLC
#
# 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
"""
Qt compatibility layer for capa IDA Pro plugin.
Handles PyQt5 (IDA < 9.2) vs PySide6 (IDA >= 9.2) differences.
This module provides a unified import interface for Qt modules and handles
API changes between Qt5 and Qt6.
"""
try:
# IDA 9.2+ uses PySide6
from PySide6 import QtGui, QtCore, QtWidgets
from PySide6.QtGui import QAction
QT_LIBRARY = "PySide6"
Signal = QtCore.Signal
except ImportError:
# Older IDA versions use PyQt5
try:
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtWidgets import QAction
QT_LIBRARY = "PyQt5"
Signal = QtCore.pyqtSignal
except ImportError:
raise ImportError("Neither PySide6 nor PyQt5 is available. Cannot initialize capa IDA plugin.")
Qt = QtCore.Qt
def qt_get_item_flag_tristate():
"""
Get the tristate item flag compatible with Qt5 and Qt6.
Qt5 (PyQt5): Uses Qt.ItemIsTristate
Qt6 (PySide6): Qt.ItemIsTristate was removed, uses Qt.ItemIsAutoTristate
ItemIsAutoTristate automatically manages tristate based on child checkboxes,
matching the original ItemIsTristate behavior where parent checkboxes reflect
the check state of their children.
Returns:
int: The appropriate flag value for the Qt version
Raises:
AttributeError: If the tristate flag cannot be found in the Qt library
"""
if QT_LIBRARY == "PySide6":
# Qt6: ItemIsTristate was removed, replaced with ItemIsAutoTristate
# Try different possible locations (API varies slightly across PySide6 versions)
if hasattr(Qt, "ItemIsAutoTristate"):
return Qt.ItemIsAutoTristate
elif hasattr(Qt, "ItemFlag") and hasattr(Qt.ItemFlag, "ItemIsAutoTristate"):
return Qt.ItemFlag.ItemIsAutoTristate
else:
raise AttributeError(
"Cannot find ItemIsAutoTristate in PySide6. "
+ "Your PySide6 version may be incompatible with capa. "
+ f"Available Qt attributes: {[attr for attr in dir(Qt) if 'Item' in attr]}"
)
else:
# Qt5: Use the original ItemIsTristate flag
return Qt.ItemIsTristate
__all__ = ["qt_get_item_flag_tristate", "Signal", "QAction", "QtGui", "QtCore", "QtWidgets"]

View File

@@ -18,7 +18,6 @@ from collections import Counter
import idc import idc
import idaapi import idaapi
from PyQt5 import QtGui, QtCore, QtWidgets
import capa.rules import capa.rules
import capa.engine import capa.engine
@@ -28,6 +27,7 @@ import capa.features.basicblock
from capa.ida.plugin.item import CapaExplorerFunctionItem from capa.ida.plugin.item import CapaExplorerFunctionItem
from capa.features.address import AbsoluteVirtualAddress, _NoAddress from capa.features.address import AbsoluteVirtualAddress, _NoAddress
from capa.ida.plugin.model import CapaExplorerDataModel from capa.ida.plugin.model import CapaExplorerDataModel
from capa.ida.plugin.qt_compat import QtGui, QtCore, Signal, QAction, QtWidgets
MAX_SECTION_SIZE = 750 MAX_SECTION_SIZE = 750
@@ -147,7 +147,7 @@ def calc_item_depth(o):
def build_action(o, display, data, slot): def build_action(o, display, data, slot):
""" """ """ """
action = QtWidgets.QAction(display, o) action = QAction(display, o)
action.setData(data) action.setData(data)
action.triggered.connect(lambda checked: slot(action)) action.triggered.connect(lambda checked: slot(action))
@@ -312,7 +312,7 @@ class CapaExplorerRulegenPreview(QtWidgets.QTextEdit):
class CapaExplorerRulegenEditor(QtWidgets.QTreeWidget): class CapaExplorerRulegenEditor(QtWidgets.QTreeWidget):
updated = QtCore.pyqtSignal() updated = Signal()
def __init__(self, preview, parent=None): def __init__(self, preview, parent=None):
""" """ """ """

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
__version__ = "9.2.1" __version__ = "9.3.1"
def get_major_version(): def get_major_version():

View File

@@ -74,7 +74,8 @@ dependencies = [
# comments and context. # comments and context.
"pyyaml>=6", "pyyaml>=6",
"colorama>=0.4", "colorama>=0.4",
"ida-settings>=2.1.0,<3", # v3 has breaking changes "ida-netnode>=3.0",
"ida-settings>=3.1.0",
"ruamel.yaml>=0.18", "ruamel.yaml>=0.18",
"pefile>=2023.2.7", "pefile>=2023.2.7",
"pyelftools>=0.31", "pyelftools>=0.31",
@@ -104,7 +105,7 @@ dependencies = [
"networkx>=3", "networkx>=3",
"dnfile>=0.15.0", "dnfile>=0.17.0",
] ]
dynamic = ["version"] dynamic = ["version"]
@@ -121,7 +122,7 @@ dev = [
# we want all developer environments to be consistent. # we want all developer environments to be consistent.
# These dependencies are not used in production environments # These dependencies are not used in production environments
# and should not conflict with other libraries/tooling. # and should not conflict with other libraries/tooling.
"pre-commit==4.2.0", "pre-commit==4.5.0",
"pytest==8.0.0", "pytest==8.0.0",
"pytest-sugar==1.1.1", "pytest-sugar==1.1.1",
"pytest-instafail==0.5.0", "pytest-instafail==0.5.0",
@@ -137,7 +138,7 @@ dev = [
"flake8-use-pathlib==0.3.0", "flake8-use-pathlib==0.3.0",
"flake8-copyright==0.2.4", "flake8-copyright==0.2.4",
"ruff==0.12.0", "ruff==0.12.0",
"black==25.1.0", "black==25.11.0",
"isort==6.0.0", "isort==6.0.0",
"mypy==1.17.1", "mypy==1.17.1",
"mypy-protobuf==3.6.0", "mypy-protobuf==3.6.0",
@@ -149,7 +150,7 @@ dev = [
"types-PyYAML==6.0.8", "types-PyYAML==6.0.8",
"types-psutil==7.0.0.20250218", "types-psutil==7.0.0.20250218",
"types_requests==2.32.0.20240712", "types_requests==2.32.0.20240712",
"types-protobuf==6.30.2.20250516", "types-protobuf==6.32.1.20250918",
"deptry==0.23.0" "deptry==0.23.0"
] ]
build = [ build = [
@@ -157,16 +158,18 @@ build = [
# we want all developer environments to be consistent. # we want all developer environments to be consistent.
# These dependencies are not used in production environments # These dependencies are not used in production environments
# and should not conflict with other libraries/tooling. # and should not conflict with other libraries/tooling.
"pyinstaller==6.14.1", "pyinstaller==6.16.0",
"setuptools==80.9.0", "setuptools==80.9.0",
"build==1.2.2" "build==1.3.0"
] ]
scripts = [ scripts = [
# can (optionally) be more lenient on dependencies here
# see comment on dependencies for more context
"jschema_to_python==1.2.3", "jschema_to_python==1.2.3",
"psutil==7.0.0", "psutil==7.1.2",
"stix2==3.0.1", "stix2==3.0.1",
"sarif_om==1.0.4", "sarif_om==1.0.4",
"requests==2.32.3", "requests>=2.32.4",
] ]
[tool.deptry] [tool.deptry]
@@ -198,7 +201,8 @@ known_first_party = [
"idc", "idc",
"java", "java",
"netnode", "netnode",
"PyQt5" "PyQt5",
"PySide6"
] ]
[tool.deptry.per_rule_ignores] [tool.deptry.per_rule_ignores]

View File

@@ -10,35 +10,35 @@ annotated-types==0.7.0
colorama==0.4.6 colorama==0.4.6
cxxfilt==0.3.0 cxxfilt==0.3.0
dncil==1.0.2 dncil==1.0.2
dnfile==0.16.4 dnfile==0.17.0
funcy==2.0 funcy==2.0
humanize==4.13.0 humanize==4.14.0
ida-netnode==3.0 ida-netnode==3.0
ida-settings==2.1.0 ida-settings==3.2.2
intervaltree==3.1.0 intervaltree==3.1.0
markdown-it-py==4.0.0 markdown-it-py==4.0.0
mdurl==0.1.2 mdurl==0.1.2
msgpack==1.0.8 msgpack==1.0.8
networkx==3.4.2 networkx==3.4.2
pefile==2024.8.26 pefile==2024.8.26
pip==25.2 pip==25.3
protobuf==6.31.1 protobuf==6.33.1
pyasn1==0.5.1 pyasn1==0.5.1
pyasn1-modules==0.3.0 pyasn1-modules==0.3.0
pycparser==2.22 pycparser==2.23
pydantic==2.11.4 pydantic==2.12.4
# pydantic pins pydantic-core, # pydantic pins pydantic-core,
# but dependabot updates these separately (which is broken) and is annoying, # but dependabot updates these separately (which is broken) and is annoying,
# so we rely on pydantic to pull in the right version of pydantic-core. # so we rely on pydantic to pull in the right version of pydantic-core.
# pydantic-core==2.23.4 # pydantic-core==2.23.4
xmltodict==0.14.2 xmltodict==1.0.2
pyelftools==0.32 pyelftools==0.32
pygments==2.19.1 pygments==2.19.1
python-flirt==0.9.2 python-flirt==0.9.2
pyyaml==6.0.2 pyyaml==6.0.2
rich==14.2.0 rich==14.2.0
ruamel-yaml==0.18.6 ruamel-yaml==0.18.6
ruamel-yaml-clib==0.2.8 ruamel-yaml-clib==0.2.14
setuptools==80.9.0 setuptools==80.9.0
six==1.17.0 six==1.17.0
sortedcontainers==2.4.0 sortedcontainers==2.4.0

2
rules

Submodule rules updated: 9e4cc28265...b0b486fe0c

View File

@@ -70,4 +70,4 @@ def test_standalone_binja_backend():
@pytest.mark.skipif(binja_present is False, reason="Skip binja tests if the binaryninja Python API is not installed") @pytest.mark.skipif(binja_present is False, reason="Skip binja tests if the binaryninja Python API is not installed")
def test_binja_version(): def test_binja_version():
version = binaryninja.core_version_info() version = binaryninja.core_version_info()
assert version.major == 5 and version.minor == 1 assert version.major == 5 and version.minor == 2

View File

@@ -2272,10 +2272,11 @@
} }
}, },
"node_modules/glob": { "node_modules/glob": {
"version": "10.4.2", "version": "10.5.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
"integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"dev": true, "dev": true,
"license": "ISC",
"dependencies": { "dependencies": {
"foreground-child": "^3.1.0", "foreground-child": "^3.1.0",
"jackspeak": "^3.1.2", "jackspeak": "^3.1.2",
@@ -2287,9 +2288,6 @@
"bin": { "bin": {
"glob": "dist/esm/bin.mjs" "glob": "dist/esm/bin.mjs"
}, },
"engines": {
"node": ">=16 || 14 >=14.18"
},
"funding": { "funding": {
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
@@ -2641,10 +2639,11 @@
} }
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
"version": "4.1.0", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"argparse": "^2.0.1" "argparse": "^2.0.1"
}, },

View File

@@ -212,6 +212,18 @@
<h2 class="mt-3">Tool Updates</h2> <h2 class="mt-3">Tool Updates</h2>
<h3 class="mt-2">v9.3.1 (<em>2025-11-19</em>)</h3>
<p class="mt-0">
This patch release fixes a missing import for the capa explorer plugin for IDA Pro.
</p>
<h3 class="mt-2">v9.3.0 (<em>2025-11-12</em>)</h3>
<p class="mt-0">
capa v9.3.0 comes with over 20 new and/or impoved rules.
For IDA users the capa explorer plugin is now available via the IDA Pro plugin repository and contains Qt compatibility layer for PyQt5 and PySide6 support.
Additionally a Binary Ninja bug has been fixed. Released binaries now include ARM64 binaries (Linux and macOS).
</p>
<h3 class="mt-2">v9.2.1 (<em>2025-06-06</em>)</h3> <h3 class="mt-2">v9.2.1 (<em>2025-06-06</em>)</h3>
<p class="mt-0"> <p class="mt-0">
This point release fixes bugs including removing an unnecessary PyInstaller warning message and enabling the standalone binary to execute on systems running older versions of glibc. This point release fixes bugs including removing an unnecessary PyInstaller warning message and enabling the standalone binary to execute on systems running older versions of glibc.