-
Notifications
You must be signed in to change notification settings - Fork 57
Capesolo update #115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: capesolo
Are you sure you want to change the base?
Capesolo update #115
Conversation
…skip_active is true (hook_sleep.c)
… 38a9847cb5ce4918bdfee2d54d5d3b79e1399cce15c7b68d86e8f0a5f48e3131)
…6b8ff55c452cc87e35d69928cccbcfc5af848db1abb4fe0364510986e068b)
Initial commit for WMI hooks
Allows ability to properly track CryptKey handles (.NET often times operates on dupe key instead of original)
…ateKey Hook CryptDuplicateKey
…rampoline allocation (hook-low=1)
- Log Process ID in NtReadVirtualMemory/NtWriteVirtualMemory/ReadProcessMemory/WriteProcessMemory if the process handle used does not represent the current running process - Remove a dupe arg from NtOpenThread - Better logging for NtGetContextThread; logs have appropriate arguments based on the context flags - Cloned this logic to NtSetContextThread as well - Added PID/TID to NtGet/SetContextThread Changes inspired by trying to detect https://research.checkpoint.com/2025/waiting-thread-hijacking/ I've found it's quite difficult to keep track of all all of the handles being mapped to various identifiers (PID/TID) from the various APIs in a signature without these improvements.
…aps=1' for loader snaps output in analysis log
…ailable WaitForDebugEventEx
…r" for shell: monitor=<pid/"explorer">
…r calls to named functions
…irst, complete scan on canary detection
…) with non-allocating get_module_name()
…han ntdll (ntdll-protect) - off by default
…king() from NtReadFile hook
Couple new thread hooks
Introduce `_pipe_sprintf` for formatted string output and `InteractiveBreakpointCallback` for handling interactive breakpoints. Update `SetConfigBP` and `SetInitialBreakpoints` to conditionally use the new callback based on configuration, enhancing breakpoint functionality for interactive debugging.
Summary of ChangesHello @enzok, 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 significantly upgrades the CAPE sandbox's capabilities by introducing an interactive debugger, strengthening its defenses against analysis, and refining its core hooking and logging infrastructure. The changes aim to provide deeper insights into malware behavior while making the sandbox more resilient to detection and evasion techniques. The codebase has been modernized for improved performance and maintainability. Highlights
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this 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 significant enhancements, primarily the implementation of Capesolo, an interactive debugger. The changes are extensive and include major refactoring and improvements across the codebase. Key updates involve a more robust 64-bit hooking mechanism, performance improvements in Yara scanning, and the removal of the problematic WoW64 workaround. Additionally, many hooks have been improved for more detailed logging and enhanced anti-analysis capabilities. I've identified a couple of issues related to memory access and logical flow that should be addressed.
| Matching = pRtlCompareMemory((PVOID)EntryPointBytes, pEntryPointBytes, ChunkSize); | ||
|
|
||
| if (Matching == ChunkSize) | ||
| { | ||
| #ifdef DEBUG_COMMENTS | ||
| DebugOutput("VerifyHeaders: Entry point matches.\n"); | ||
| #endif | ||
| RetVal = 1; | ||
| } | ||
| else | ||
| { | ||
| DebugOutput("VerifyHeaders: Entry point does not match, 0x%x of 0x%x matching\n", Matching, ChunkSize); | ||
| RetVal = 0; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for verifying headers and the entry point is flawed. The result of the header check (RetVal) is overwritten by the result of the entry point check. If the header check fails (RetVal = 0) but the entry point check succeeds, the function will incorrectly return 1 (match), indicating an overall success. The function should return 0 if any of the checks fail.
Matching = pRtlCompareMemory((PVOID)EntryPointBytes, pEntryPointBytes, ChunkSize);
if (Matching != ChunkSize)
{
DebugOutput("VerifyHeaders: Entry point does not match, 0x%x of 0x%x matching\n", Matching, ChunkSize);
RetVal = 0;
}
#ifdef DEBUG_COMMENTS
else if (RetVal == 1)
{
DebugOutput("VerifyHeaders: Entry point matches.\n");
}
#endif| PDWORD AddressOfNames = (PDWORD)((PUCHAR)Base + ExportDir->AddressOfNames); | ||
| PWORD AddressOfNameOrdinals = (PWORD)((PUCHAR)Base + ExportDir->AddressOfNameOrdinals); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pointers AddressOfNames and AddressOfNameOrdinals are calculated from the export directory but are not checked for accessibility before being used inside the loop. This could lead to a crash if the PE header is malformed or corrupted. It's good practice to validate these pointers after they are calculated, similar to how AddressOfFunctions is checked.
PDWORD AddressOfNames = (PDWORD)((PUCHAR)Base + ExportDir->AddressOfNames);
PWORD AddressOfNameOrdinals = (PWORD)((PUCHAR)Base + ExportDir->AddressOfNameOrdinals);
if (!IsAddressAccessible(AddressOfNames) || !IsAddressAccessible(AddressOfNameOrdinals))
return NULL;Moved the declaration of the function pointer _NtQueryInformationThread from static to non-static, allowing broader access outside the current translation unit.
Implement Capesolo support