Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions modules/processing/behavior.py
Original file line number Diff line number Diff line change
Expand Up @@ -779,9 +779,8 @@ def event_apicall(self, call, process):
and (access & 0x80000000 or access & 0x10000000 or access & 0x02000000 or access & 0x1)
and filename not in self.read_files
):
# self.read_files.append(filename)
self._filtering_helper(self.read_files, srcfilename)
self._add_file_activity(process, "read_files", srcfilename)
self._filtering_helper(self.read_files, srcfilename or filename)
self._add_file_activity(process, "read_files", srcfilename or filename)
if (
access
and (access & 0x40000000 or access & 0x10000000 or access & 0x02000000 or access & 0x6)
Expand Down Expand Up @@ -947,7 +946,13 @@ def __init__(self, details=False):
{
"event": "write",
"object": "registry",
"apis": ["RegSetValueExA", "RegSetValueExW"],
"apis": [
"RegSetValueExA",
"RegSetValueExW",
"NtSetValueKey",
"RegSetValueA",
"RegSetValueW",
],
"args": [("regkey", "FullName"), ("content", "Buffer")],
},
{
Expand Down Expand Up @@ -1042,6 +1047,10 @@ def _get_service_action(control_code):
item = self.api_map.get(call["api"])
if item:
args = _load_args(call)
if call["api"] in ("RegCreateKeyExA", "RegCreateKeyExW"):
disposition = args.get("Disposition")
if disposition is not None and int(disposition) != 1:
return None
self.eid += 1

event = {
Expand Down
81 changes: 80 additions & 1 deletion tests/test_behavior.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
# See the file 'docs/LICENSE' for copying permission.

from lib.cuckoo.common.config import Config
from modules.processing.behavior import ParseProcessLog
from lib.cuckoo.common.dictionary import Dictionary
from modules.processing.behavior import Enhanced, ParseProcessLog, Summary

cfg = Config("processing")

Expand All @@ -14,3 +15,81 @@ def test_init(self):
str(ParseProcessLog("CAPEv2/tests/test_bson.bson", cfg.behavior))
== "<ParseProcessLog log-path: CAPEv2/tests/test_bson.bson>"
)


class TestSummaryAndEnhanced:
def test_summary_read_files_and_file_activities(self):
options = Dictionary({"replace_patterns": False, "file_activities": True})
summary = Summary(options=options)
process = {
"process_id": 2256,
"file_activities": {
"read_files": [],
"write_files": [],
"delete_files": [],
},
}
call = {
"api": "NtOpenFile",
"category": "filesystem",
"status": True,
"arguments": [
{"name": "FileHandle", "value": "0x000002cc"},
{"name": "DesiredAccess", "value": "0x00100021"},
{"name": "FileName", "value": r"C:\Users\Bruno\AppData\Local\Temp\data.bin"},
{"name": "ShareAccess", "value": "5"},
],
}
summary.event_apicall(call, process)
result = summary.run()
assert r"C:\Users\Bruno\AppData\Local\Temp\data.bin" in result["read_files"]
assert r"C:\Users\Bruno\AppData\Local\Temp\data.bin" in process["file_activities"]["read_files"]

def test_enhanced_registry_writes_and_disposition(self):
enhanced = Enhanced()

nt_set_call = {
"api": "NtSetValueKey",
"category": "registry",
"timestamp": "2026-09-29 13:42:00,360",
"arguments": [
{
"name": "FullName",
"value": r"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\Cache\Cookies\CachePrefix",
},
{"name": "Buffer", "value": "Cookie:"},
],
}
ev = enhanced._process_call(nt_set_call)
assert ev is not None
assert ev["event"] == "write"
assert ev["object"] == "registry"
assert ev["data"]["content"] == "Cookie:"

# RegCreateKeyExW with Disposition=2 (REG_OPENED_EXISTING_KEY) should not be treated as a write
open_existing_call = {
"api": "RegCreateKeyExW",
"category": "registry",
"timestamp": "2026-09-29 13:42:00,400",
"arguments": [
{"name": "FullName", "value": r"HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\Schannel"},
{"name": "Disposition", "value": "2"},
],
}
assert enhanced._process_call(open_existing_call) is None

# RegCreateKeyExW with Disposition=1 (REG_CREATED_NEW_KEY) is recorded as a write
create_new_call = {
"api": "RegCreateKeyExW",
"category": "registry",
"timestamp": "2026-09-29 13:42:00,410",
"arguments": [
{"name": "FullName", "value": r"HKEY_CURRENT_USER\Software\NewMalwareKey"},
{"name": "Disposition", "value": "1"},
],
}
ev_create = enhanced._process_call(create_new_call)
assert ev_create is not None
assert ev_create["event"] == "write"
assert ev_create["data"]["regkey"] == r"HKEY_CURRENT_USER\Software\NewMalwareKey"

Loading