mirror of
https://github.com/mandiant/capa.git
synced 2025-12-05 20:40:05 -08:00
Merge branch 'master' into idalib-tests
This commit is contained in:
@@ -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
1
.gitignore
vendored
@@ -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
|
||||||
|
|||||||
55
CHANGELOG.md
55
CHANGELOG.md
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
79
capa/ida/plugin/qt_compat.py
Normal file
79
capa/ida/plugin/qt_compat.py
Normal 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"]
|
||||||
@@ -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):
|
||||||
""" """
|
""" """
|
||||||
|
|||||||
@@ -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():
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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
2
rules
Submodule rules updated: 9e4cc28265...b0b486fe0c
@@ -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
|
||||||
|
|||||||
17
web/explorer/package-lock.json
generated
17
web/explorer/package-lock.json
generated
@@ -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"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user