Skip to content

Commit 2e2391e

Browse files
doomedravenenzokYungBinarykevoreillyFernandoDoming
authored
sync (#2761)
* Update AdaptixBeacon yara and add NitrogenBunnyDownloader yara * add missing hash * add missing update * Gemini nags * Additional Rhadamanthys patterns * Switch Suricata installation to version 7.0 Comment out the repository for Suricata 8 and use Suricata 7.0 instead. * Remove test_handle_process_invalid_data() from tests/test_analyzer.py * Tweak Rhadamanthys patterns - removed highly variable jump size in conditional jump (0x2e6 bytes code, size highly brittle) - replaced eax register in nice characteristic pattern as it can only be eax, since pattern contains the xor eax, eax instruction by which the code zeroes) * Rhadamanthys anti-anti detonation bypass * Rhadamanthys detection patterns * Enable protocol extended information to be generated without a TLS master secret (#2739) * Update NitroBunnyDownloader yara * Bump django from 5.1.13 to 5.1.14 (#2742) Bumps [django](https://github.com/django/django) from 5.1.13 to 5.1.14. - [Commits](django/django@5.1.13...5.1.14) --- updated-dependencies: - dependency-name: django dependency-version: 5.1.14 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update startup.py * Fix path handling for SHA256 calculation * Update startup.py * Monitor updates: see changelog for details * analyzer: remove obsolete 'suspended' parameter from CommandPipeHandler * Update routing.rst * Fix error list entry format in demux.py * prevent linux parsing errors (#2744) * Rhadamanthys unhook bypass * Add Suricata host (#2745) * Rename surihhost to surihost in search.html * Add 'surihost' key to Suricata alert mapping * Update lib/cuckoo/common/web_utils.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Monitor update: Add config option for monitor injection into supplied pid or "explorer" for shell: monitor=<pid/"explorer"> * SmokeLoader 2025 * Update installation step to include KnowledgeBaseBot Install dependencies from both requirements files. * Bump django from 5.1.13 to 5.1.14 (#2749) Bumps [django](https://github.com/django/django) from 5.1.13 to 5.1.14. - [Commits](django/django@5.1.13...5.1.14) --- updated-dependencies: - dependency-name: django dependency-version: 5.1.14 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ci: Update requirements.txt * Refactor auto_answer.yml to streamline dependency installation Updated the workflow to install dependencies using uv run with specified requirements files. * fix docs * Fix a bug that prevents terminal status from being reported by the agent (#2753) Updates the POST /status endpoint to unset the async subprocess if the new status is terminal. This makes GET /status report the final analysis state, rather than the child process state. * Fix 'machines' vars on Azure (#2755) * Monitor update: Fix issue with RESUME: monitor message from NtResumeProcess hook * Bump pypdf from 5.2.0 to 6.4.0 (#2757) Bumps [pypdf](https://github.com/py-pdf/pypdf) from 5.2.0 to 6.4.0. - [Release notes](https://github.com/py-pdf/pypdf/releases) - [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md) - [Commits](py-pdf/pypdf@5.2.0...6.4.0) --- updated-dependencies: - dependency-name: pypdf dependency-version: 6.4.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Prevent on_complete execution for matched signatures (#2758) --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: enzok <7831008+enzok@users.noreply.github.com> Co-authored-by: Yung Binary <93540406+YungBinary@users.noreply.github.com> Co-authored-by: Kevin O'Reilly <kevoreilly@gmail.com> Co-authored-by: Fernando Domínguez <6620286+FernandoDoming@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: David Santos <44490090+dsecuma@users.noreply.github.com> Co-authored-by: Bart <3075118+bartblaze@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: GitHub Actions <action@github.com> Co-authored-by: Josh Feather <142008135+josh-feather@users.noreply.github.com> Co-authored-by: Lilian <86776930+Grand-Duc@users.noreply.github.com>
1 parent 7cd9553 commit 2e2391e

File tree

29 files changed

+176
-80
lines changed

29 files changed

+176
-80
lines changed

.github/workflows/auto_answer.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ jobs:
2222
with:
2323
enable-cache: true
2424

25-
- name: Install the project
26-
run: uv run pip install -r requirements.txt
27-
2825
- name: Run the answer bot with uv run
2926
env:
3027
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3128
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
3229
ISSUE_NUMBER: ${{ github.event.issue.number }}
3330
REPO_NAME: ${{ github.repository }}
34-
# This single step installs dependencies (if needed) and runs the script
35-
run: cd KnowledgeBaseBot && uv run python auto_answer_bot.py
31+
run: |
32+
cd KnowledgeBaseBot && \
33+
uv run \
34+
--with-requirements ../requirements.txt \
35+
--with-requirements requirements.txt \
36+
python auto_answer_bot.py

agent/agent.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ def _missing_(cls, value):
9292
return None
9393

9494

95+
TERMINAL_STATUSES = [Status.COMPLETE, Status.FAILED, Status.EXCEPTION]
96+
9597
AGENT_BROWSER_EXT_PATH = ""
9698
AGENT_BROWSER_LOCK = Lock()
9799
ANALYZER_FOLDER = ""
@@ -494,6 +496,11 @@ def put_status():
494496
except ValueError:
495497
return json_error(400, "No valid status has been provided")
496498

499+
# If the new status is terminal, unset the async subprocess so /status reports
500+
# the final analysis state rather than the child process state.
501+
if status in TERMINAL_STATUSES:
502+
state["async_subprocess"] = None
503+
497504
state["status"] = status
498505
state["description"] = request.form.get("description")
499506
return json_success("Analysis status updated")

agent/test_agent.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,34 @@ def test_async_failure(self):
639639
js = self.confirm_status(str(agent.Status.FAILED))
640640
assert "process_id" not in js
641641

642+
def test_async_manual_status_override(self):
643+
"""Test that a manual status update overrides an in-progress async process."""
644+
# Upload a Python file that sleeps for a short period, to ensure the
645+
# async subprocess is running while we override the status.
646+
file_contents = (
647+
"import time",
648+
"time.sleep(10)",
649+
)
650+
651+
filepath = self.store_file(file_contents)
652+
form = {"filepath": filepath, "async": 1}
653+
654+
execpy_resp = self.post_form("execpy", form)
655+
assert execpy_resp.get("message") == "Successfully spawned command"
656+
657+
# While the subprocess is running, the status should initially be RUNNING.
658+
self.confirm_status(str(agent.Status.RUNNING))
659+
660+
# Manually override the status to COMPLETE via POST /status.
661+
override_form = {
662+
"status": str(agent.Status.COMPLETE),
663+
"description": "beep boop"
664+
}
665+
status_resp = self.post_form("status", override_form)
666+
assert status_resp.get("message") == "Analysis status updated"
667+
668+
self.confirm_status(str(agent.Status.COMPLETE))
669+
642670
def test_execute(self):
643671
"""Test executing the 'date' command."""
644672
if sys.platform == "win32":

analyzer/windows/analyzer.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,7 +1332,6 @@ def _handle_process(self, data):
13321332
"""Request for injection into a process."""
13331333
# Parse the process identifier.
13341334
# PROCESS:1:1824,2856
1335-
suspended = False
13361335
process_id = thread_id = None
13371336
# We parse the process ID.
13381337
pid_s, tid_s = data.split(b",", 1)
@@ -1352,7 +1351,6 @@ def _handle_process(self, data):
13521351
config=self.analyzer.config,
13531352
pid=process_id,
13541353
thread_id=thread_id,
1355-
suspended=suspended,
13561354
)
13571355
filepath = proc.get_filepath() # .encode('utf8', 'replace')
13581356
# if it's a URL analysis, provide the URL to all processes as

analyzer/windows/data/yara/Rhadamanthys.yar

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,26 @@ rule Rhadamanthys
1111
condition:
1212
2 of them
1313
}
14+
15+
rule RhadaAnti
16+
{
17+
meta:
18+
author = "kevoreilly"
19+
cape_options = "bp0=$anti,action0=jmp,count=0,ntdll-protect=0,dump-limit=0"
20+
strings:
21+
$anti = {74 0E FF 75 ?? 8D 45 ?? 50 E8 [4] 59 59 8D 45 ?? 50 56 68 04 01 00 00}
22+
condition:
23+
all of them
24+
}
25+
26+
rule RhadUnhook
27+
{
28+
meta:
29+
cape_options = "bp0=$scan*,action0=scan:rbx,count=0,patch=$target+21:9090"
30+
packed = "dd4af0f1888977f6d9eb820b19f4afc2a73d1c494a132ab4261498328005dda7"
31+
strings:
32+
$scan = {48 85 DB 0F 84 E1 00 00 00 4C 8D 44 24 70 48 8D 54 24 40 48 8B CE 44 89 7C 24 50 4C 89 64 24 40 48 C7 44 24 48 00 00 00 00 C6 44 24 54 00 FF}
33+
$target = {4D 85 C9 48 8B C6 4A 8D 0C 1E 74 15 48 2B D8 49 2B DB 8A 04 0B 88 01 48 83 C1 01 49 83 E9 01 75 F1 5F 5E 5D 5B C3}
34+
condition:
35+
any of them
36+
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
rule SmokeLoader
1+
rule SmokeInjector
22
{
33
meta:
44
author = "kevoreilly"
5-
description = "SmokeLoader Payload"
6-
cape_options = "bp0=$gate+19,action0=DumpSectionViews,count=1"
5+
cape_options = "monitor=explorer"
6+
packed = "d38f9ab81a054203e5b5940e6d34f3c8766f4f4104b14840e4695df511feaa30"
77
strings:
8-
$gate = {68 [2] 00 00 50 E8 [4] 8B 45 ?? 89 F1 8B 55 ?? 9A [2] 40 00 33 00 89 F9 89 FA 81 C1 [2] 00 00 81 C2 [2] 00 00 89 0A 8B 46 ?? 03 45 ?? 8B 4D ?? 8B 55 ?? 9A [2] 40 00 33 00}
8+
$dec1 = {80 04 08 [0-7] (49|83 E9 01) [0-7] 41 [0-7] 81 F1 [2] 00 00 [0-7] 01 D9 [0-7] FF E1}
99
condition:
1010
uint16(0) == 0x5A4D and any of them
1111
}

analyzer/windows/dll/capemon.dll

512 Bytes
Binary file not shown.
512 Bytes
Binary file not shown.

analyzer/windows/tests/test_analyzer.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -986,23 +986,3 @@ def test_handle_process(self, mock_process):
986986
self.assertIsNotNone(ana.LASTINJECT_TIME)
987987
mock_process.assert_called_once()
988988
self.assertEqual(1, ana.NUM_INJECTED)
989-
990-
@patch("analyzer.Process")
991-
def test_handle_process_invalid_data(self, mock_process):
992-
ana = self.analyzer
993-
with self.assertRaises(ValueError):
994-
data = bytes("does not have a colon".encode())
995-
self.pipe_handler._handle_process(data=data)
996-
with self.assertRaises(ValueError):
997-
data = bytes("has:too:many:colons".encode())
998-
self.pipe_handler._handle_process(data=data)
999-
1000-
data = bytes("no_comma:non_digits".encode())
1001-
self.pipe_handler._handle_process(data=data)
1002-
self.assertIsNone(ana.LASTINJECT_TIME)
1003-
mock_process.assert_not_called()
1004-
1005-
data = bytes("with_comma:non_digits,non_digits".encode())
1006-
self.pipe_handler._handle_process(data=data)
1007-
self.assertIsNone(ana.LASTINJECT_TIME)
1008-
mock_process.assert_not_called()

changelog.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
1+
### [24.11.2025]
2+
* Monitor update: Fix issue with RESUME: monitor message from NtResumeProcess hook
3+
4+
### [17.11.2025]
5+
* Monitor update: Add config option for monitor injection into supplied pid or "explorer" for shell: monitor=<pid/"explorer">
6+
7+
### [06.11.2025]
8+
* Monitor updates:
9+
* path_from_object_attributes(): fix issue with memcpy from bad ObjectName->Buffer (e.g. 0a9d9b402fb39cf8df21ca4e68b84577c39b3ecf00415c999b28fcc92a695663)
10+
* Fix/improve exception handling code which queries current SEH handler
11+
* Harden our_stackwalk() against invalid stack pointers (hooking_64)
12+
* Add exported function name logging to thread hooks: NtCreateThreadEx, CreateThread, NtQueueApcThread, NtQueueApcThreadEx
13+
14+
### [03.11.2025]
15+
* Rhadamanthys:
16+
* static config extraction - thanks @YungBinary
17+
* anti-anti detonation bypass
18+
119
### [22.10.2025]
20+
* Add monitor injection to previously unused RESUME: monitor message handler _handle_resume()
221
* Remove obsolete 'suspended' parameter from PROCESS monitor message
322
* Monitor updates:
423
* WriteMemoryHandler: prevent analysis log spam for small PE writes
524
* Cap per-process messages to prevent detonation slow-down & failure in e.g. 9f8333d81c13ea426953b758140836cff2cf7e7f32e36738f118c6257c6efd34
625
* Experimental debugger action 'guard' to trap on guard violation
7-
* (origin/capemon, origin/HEAD) YaraHarness: write rules canary detection to analysis log
8-
* YaraHarness: simplify 'dump' option
26+
* YaraHarness: write rules canary detection to analysis log & simplify 'dump' option
927
* Deprecate Win7 wow64 breakpoint workaround
1028
* Implement Gemini suggestions from #111
1129
* Merge pull request #111 from StephanTLavavej/unordered_map

0 commit comments

Comments
 (0)