Skip to content

Add yara-timeout setting for in-monitor scans#121

Open
ncatlin wants to merge 2 commits intokevoreilly:capemonfrom
ncatlin:yaratimeout
Open

Add yara-timeout setting for in-monitor scans#121
ncatlin wants to merge 2 commits intokevoreilly:capemonfrom
ncatlin:yaratimeout

Conversation

@ncatlin
Copy link

@ncatlin ncatlin commented Jan 25, 2026

Hi, my first experience of using CAPE was spending hours trying to debug why no behavioural information or memory dumps were being reported. It turned out that I had been overambitious with YARA rules and the memory scanner was breaching its timeout (and not logging it) but there was no way to configure this hardcoded 1-second duration without completely recompiling and replacing capemon.dll.

Getting tired of doing that - so this PR adds a simple 'yara-timeout' monitor option that overrides the default - if supplied - otherwise there is no effect on behaviour.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ncatlin, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the flexibility of CAPE's in-monitor YARA scanning by making the scan timeout configurable. Previously, a fixed 1-second timeout could lead to incomplete analysis and missing data when YARA rules were complex or extensive. The change allows users to adjust this timeout, preventing silent failures and ensuring more comprehensive behavioral analysis and memory dumps, thereby improving the reliability and diagnostic capabilities of the system.

Highlights

  • Configurable YARA Timeout: Introduced a new yara-timeout configuration option, allowing users to specify the duration for in-monitor YARA scans.
  • Removed Hardcoded Timeout: The previously hardcoded 1-second timeout for YARA memory scans has been replaced with the configurable g_config.yara_timeout value.
  • Configuration Integration: The new yara-timeout setting is now parsed from the configuration file and initialized with a default value of 1 second.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a configurable yara-timeout setting for in-monitor YARA scans, replacing the previous hardcoded 1-second timeout. This is a valuable addition, as it provides more flexibility for users with complex YARA rules that may require longer scan times. The changes in config.h, config.c, and YaraHarness.c correctly implement this new configuration option by adding the yara_timeout field to the global configuration, parsing it from the config file, setting a default value, and using it in the YaraScan function. My review includes one suggestion to improve the robustness of the configuration parsing.

Comment on lines 1323 to 1329
else if (!stricmp(key, "yara-timeout")) {
g_config.yara_timeout = (int)strtol(value, NULL, 10);
if (g_config.yara_timeout == 0)
DebugOutput("In-monitor YARA scan timeout set to unlimited.\n");
else
DebugOutput("In-monitor YARA scan timeout set to %d seconds.\n", g_config.yara_timeout);
}
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 strtol function is used to parse the yara-timeout value, but there's no error handling. If an invalid string (e.g., "abc") is provided, strtol will return 0, which will be interpreted as an unlimited timeout. This could lead to unexpected behavior if the user makes a typo in the configuration. It's better to validate the input to ensure it's a valid non-negative integer and log an error for invalid values.

else if (!stricmp(key, "yara-timeout")) {
	char *endptr;
	long timeout = strtol(value, &endptr, 10);

	if (endptr == value || *endptr != '\0' || timeout < 0) {
		DebugOutput("Invalid value for yara-timeout: '%s'. Must be a non-negative integer.\n", value);
	} else {
		g_config.yara_timeout = (int)timeout;
		if (g_config.yara_timeout == 0)
			DebugOutput("In-monitor YARA scan timeout set to unlimited.\n");
		else
			DebugOutput("In-monitor YARA scan timeout set to %d seconds.\n", g_config.yara_timeout);
	}
}

Copy link
Author

Choose a reason for hiding this comment

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

Error handling was in my first attempt and happy to re-add it, there just isn't any error handling in the rest of the configuration parsing and I didn't want to add clutter - so removed it to fit in with all the other strtol parsing.

Invalid values will result in a Debug log being emitted, correctly showing the timeout is disabled - unless the user passes a negative value for some reason, which will also result there being no timeout.

@kevoreilly
Copy link
Owner

Hi, thank you for this PR, it looks great. I will review and merge it tomorrow...

... but I am too intrigued to wait until then to ask how, on your first time using cape, you have ended up with monitor yara sigs that are pushing the scan timeout - what yara sigs have you added and what do they do?!

@ncatlin
Copy link
Author

ncatlin commented Jan 25, 2026

It's a good question - i've tried to replicate it with some profiling and think I was misremembering a bit.

So I did a few test scans with 30-40 rules from the base and community repos, and while most were <1ms duration, there were a few >100ms scans

2026-01-25 19:53:03,692 [root] DEBUG: 3224: YaraScan called
2026-01-25 19:53:03,692 [root] DEBUG: 3224: YaraScan: Scanning 0x00007FF79F950000, size 0x49c0a4
2026-01-25 19:53:03,911 [root] DEBUG: 3224: YaraScan: Scanned 0x00007FF79F950000 (size 0x49c0a4)  [after 209.856 ms, 209856 us].
2026-01-25 19:53:15,230 [root] DEBUG: 6232: YaraScan: Scanned 0x0000000064090000 (size 0x30b864)  [after 453.264 ms, 453264 us].
2026-01-25 19:53:15,738 [root] DEBUG: 6232: YaraScan: Scanned 0x0000000063500000 (size 0x9ed2d8)  [after 487.945 ms, 487945 us].
2026-01-25 19:53:16,940 [root] DEBUG: 6232: YaraScan: Scanned 0x0000000063500000 (size 0x9ed2d8)  [after 428.651 ms, 428651 us].

So if you have more than a few dozen rules and you are scanning regions >10 mb, you will almost certainly hit timeouts and I'm confident this feature is still useful to have.

The real problem though (and now I remember why it was hard to debug) was this:

2026-01-25 20:07:59,041 [root] DEBUG: 2156: YaraScan: Scanning 0x00700000, size 0x13d50e
2026-01-25 20:07:59,056 [root] DEBUG: 2156: YaraScan: Failed to scan 0x00700000 (size 0x13d50e) [after 11.739 ms, 11739 us] (result = 28).
2026-01-25 20:07:59,056 [root] DEBUG: 2156: Yara error: Internal error: 28
2026-01-25 20:07:59,056 [root] DEBUG: 2156: ProcessImageBase: Main module image at 0x00700000 unmodified (entropy change 0.000000e+00)
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan called
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan: Scanning 0x73640000, size 0x40
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan: Failed to scan 0x73640000 (size 0x40) [after 0.406 ms, 406 us] (result = 28).
2026-01-25 20:07:59,072 [root] DEBUG: 2156: Yara error: Internal error: 28
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan called
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan: Scanning 0x77249000, size 0x2378
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan: Failed to scan 0x77249000 (size 0x2378) [after 0.479 ms, 479 us] (result = 28).
2026-01-25 20:07:59,072 [root] DEBUG: 2156: Yara error: Internal error: 28
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan called
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan: Scanning 0x77249000, size 0x2378
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan: Failed to scan 0x77249000 (size 0x2378) [after 0.440 ms, 440 us] (result = 28).
2026-01-25 20:07:59,072 [root] DEBUG: 2156: Yara error: Internal error: 28
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan called
2026-01-25 20:07:59,072 [root] DEBUG: 2156: YaraScan: Scanning 0x7363F000, size 0xa18
2026-01-25 20:07:59,088 [root] DEBUG: 2156: YaraScan: Failed to scan 0x7363F000 (size 0xa18) [after 0.692 ms, 692 us] (result = 28).
2026-01-25 20:07:59,088 [root] DEBUG: 2156: Yara error: Internal error: 28

I can't replicate this using yara.exe to scan dumped memory, but from what I can tell of the YARA source code, this happens when it fails on warnings - possibly because a rule has a string matching 60k+ times.

https://github.com/CAPESandbox/community/blob/master/data/yara/binaries/indicator_tools.yar causes this even when it's the only rule file. I guess the lesson here is to be very careful with passing only the bare minimum of rules for runtime scanning, and do your bulk YARA work on downloaded memory dumps.

@kevoreilly
Copy link
Owner

Yes you hit on exactly where I was going with my question, as it sounds like you cannot be using the monitor yaras for what they are intended for, which is not detection in the classic sense. Their only reason for existing is to allow options in the cape_options metadata to be applied dynamically. If you are adding sigs with no cape_options metadata then you are definitely wasting your time!

@kevoreilly
Copy link
Owner

I still like the PR tho 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants