Skip to content
Open
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
51 changes: 51 additions & 0 deletions modules/signatures/windows/ransomware_extensionhijack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright (C) 2026 Kevin Ross
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from lib.cuckoo.common.abstracts import Signature

class RansomwareSetsIcon(Signature):
name = "ransomware_sets_icon"
Comment on lines +18 to +19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The class name RansomwareSetsIcon and signature name ransomware_sets_icon are misleading given the signature's functionality. It detects both icon changes and broader file-extension hijacking via UserChoice keys. To improve clarity and align with the filename and PR's intent, I suggest renaming them to RansomwareExtensionHijack and ransomware_extension_hijack respectively.

Suggested change
class RansomwareSetsIcon(Signature):
name = "ransomware_sets_icon"
class RansomwareExtensionHijack(Signature):
name = "ransomware_extension_hijack"

description = "Modifies registry keys for file-extension hijacking, possible ransomware behavior"
severity = 3
categories = ["ransomware"]
authors = ["Kevin Ross"]
minimum = "1.3"
evented = True
ttps = ["T1486", "T1564"]
mbcs = ["OB0008", "E1486"]

filter_apinames = {"RegSetValueExA", "RegSetValueExW"}

def __init__(self, *args, **kwargs):
Signature.__init__(self, *args, **kwargs)
self.ret = False

def on_call(self, call, process):
filepath = self.get_argument(call, "Buffer")
regkey = self.get_argument(call, "FullName")

if isinstance(filepath, str) and isinstance(regkey, str):
filepath_lower = filepath.lower()
regkey_lower = regkey.lower()

is_icon_hijack = filepath_lower.endswith(".ico") and (r"\defaulticon" in regkey_lower or r"\applications" in regkey_lower)
is_userchoice_hijack = r"\userchoice" in regkey_lower
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The condition for is_userchoice_hijack is very broad. It flags any registry write to a key path containing \userchoice as long as the data being written is a string. This is likely to cause false positives, as legitimate actions like changing a default program also modify these keys. To improve accuracy, this check should be more specific. For example, you could verify that the registry value being modified is ProgId and potentially inspect its new value for suspicious patterns.


if is_icon_hijack or is_userchoice_hijack:
self.mark_call()
self.ret = True

def on_complete(self):
return self.ret