Skip to content

Conversation

@cccs-mog
Copy link
Contributor

No description provided.

@cccs-mog cccs-mog marked this pull request as draft July 30, 2025 16:42
Copy link

@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.

Summary of Changes

Hello @cccs-mog, 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!

I've implemented a suite of anti-anti-debug techniques to bolster the resilience of the monitoring system against detection by debuggers and malware. Additionally, I've included a minor fix for Visual Studio project configurations to ensure correct MASM assembly file compilation.

Highlights

  • Anti-Anti-Debug Stealth: I've introduced multiple techniques to counteract debugger detection, including spoofing debug flags, preventing handle enumeration, and manipulating API call returns to mislead debuggers.
  • Visual Studio Build Fix: I've corrected the build exclusion conditions for MASM assembly files in capemon.vcxproj to ensure proper compilation across different configurations.
  • New API Hooking: I've added hooks for NtDebugActiveProcess, DbgUiDebugActiveProcess, GenerateConsoleCtrlEvent, and BlockInput to intercept and modify their behavior for anti-anti-debug purposes.
  • Debug Register Obfuscation: I've implemented logic within RtlWow64GetThreadContext to clear debug registers (Dr0-Dr3), making it harder for debuggers to set hardware breakpoints.
  • Critical Process Protection: I've modified NtClose to handle object closing exceptions gracefully and NtOpenProcess to prevent opening critical system processes like csrss.exe.
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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

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 issue 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 or fill out our survey to provide feedback.

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

@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 several anti-anti-debugging techniques and a fix for the Visual Studio project file. While the intent is to improve stealth capabilities, the implementation has introduced a number of critical issues, including memory corruption, memory leaks, and incorrect logic that could lead to crashes or unpredictable behavior. The Visual Studio project file changes also appear to be incorrect and may break the build for certain configurations. These issues should be addressed before merging.

@kevoreilly
Copy link
Owner

Wow thank you this looks great!

Could maybe just use existing GetThreadContextHandler for RtlWow64GetThreadContext too as it takes care of zeroing drs.

@cccs-mog
Copy link
Contributor Author

cccs-mog commented Aug 5, 2025

Made the change, still making some tests, let me know if there is issue with any of it and if things are fine. Happy to make it ready for merging.

@kevoreilly
Copy link
Owner

kevoreilly commented Aug 5, 2025

Thanks for that - looks much better.

I've had a closer look at the PR and I do have a reservation in that many of the anti-debug techniques that are quoted and remediated do not apply to capemon as it is not a debugger in the classic sense, at least not as far as Windows is concerned.

I am reluctant to add code to capemon that is not relevant in its normal configuration, and the following techniques would only become relevant if a 'proper' debugger like windbg or x64dbg was attached to a process also monitored by capemon:

  • CheckRemoteDebuggerPresent()
  • NtDebugActiveProcess()
  • DbgUiDebugActiveProcess()
  • GenerateConsoleCtrlEvent()
  • BlockInput()
  • OpenProcess(csrss.exe)

None of these techniques is capable of detecting the debugger in capemon (which was designed for precisely this reason), nor hooks, so they are ultimately ineffective.

@cccs-mog
Copy link
Contributor Author

cccs-mog commented Aug 5, 2025

That is understandable, if capemon debugger is not affected by this then they probably should not be included. I could remove those specifics techniques and keep the others if you see value in them. It would leave NtClose object handles, RtlWow64GetThreadContext with the zeroing of drs and NtYieldExecution.

@kevoreilly
Copy link
Owner

I definitely see value in the RtlWow64GetThreadContext hook improvement. I guess for the other two the question is: can they detect capemon? From reading the descriptions of the techniques it's not clear to me if they can, but the proof may be in the pudding. Can the example snippets be compiled and tested?

@cccs-mog
Copy link
Contributor Author

cccs-mog commented Aug 5, 2025

Alright I will look into testing/compiling those and comment back. As well as removing the unecessary ones.

@kevoreilly
Copy link
Owner

Thank you!

@cccs-mog
Copy link
Contributor Author

Alright so I was able to test out and seem that the hooks are useful for two of the 3 techniques remaining. I added the test in the PR. The hook technique in NtClose is commented out for now since it does crash the execution when running the pNtQueryObject function but I haven't had time to look closely. It doesn't seem that the antidebug techniques require this so it could be removed as well. I assume this is what the consensus is going to be but keeping it commented if you want to take a closer look at this one. Currently working on a full test suite for all the techniques to see how capemon fare and might do modification depending on the result. Sorry for the multiple commits, seem like my software suite is messing things up a little but should be fine now !

@kevoreilly
Copy link
Owner

Thanks for the updates - am bogged down with some other stuff but will hopefully get to this soon.

@mhdo298
Copy link
Contributor

mhdo298 commented Aug 21, 2025

Hi, I've been testing with al-khaser and saw that its SeDebugPrivilege is able to detect capemon in an analysis run by CAPE, while directly running the tool in the same snapshot would pass the check. Not sure if I've misconfigured anything - I did recompile capemon, but this was already happnening with the stock version shipped with CAPE. The OpenProcess(csrss.exe) patch might be relevant to default capemon because of this?

Edit: Turns out running an analysis without a monitor already fails this test, so I guess this is a CAPE thing and not neccessarily a capemon thing?

@cccs-mog
Copy link
Contributor Author

Hi @mhdo298, I will be testing this out as well. If this was caused by CAPE this would be because of grant_debug_privilege() inside the analyzer I suppose it could be that the without monitor analysis inherit this ? Regarding capemon, based on @kevoreilly comment this was not identified as a problem, but I am willing to test this one out if needed. The test in Al-Khaser is the default one so testing should be easy: https://github.com/ayoubfaouzi/al-khaser/blob/master/al-khaser/AntiDebug/SeDebugPrivilege.cpp.

@mhdo298
Copy link
Contributor

mhdo298 commented Aug 23, 2025

Hi @cccs-mog, I see that CAPE is only giving the permission so that injection works. I think a solution to this would be to revoke the privilege after the injection is done, and I’ll test things out more with CAPE to verify that this doesn’t break anything else. This probably means that capemon does not need to be patched for this test, but rather CAPE itself.

@kevoreilly
Copy link
Owner

kevoreilly commented Sep 11, 2025

Thanks for the test code. I am happy to see that capemon can trace the full execution using hardware breakpoints whilst passing all the tests:

 Close handle test: true
 Hardware breakpoint test: true
 NTYieldExecution test: true

0x00007FF776D110C2  C744246010001000         MOV       DWORD [RSP+0x60], 0x100010    
0x00007FF776D110CA  FF15380F0000             CALL      GetCurrentThread               RAX=0xfffffffffffffffe
0x00007FF776D110D0  488BC8                   MOV       RCX, RAX                       RCX=0xfffffffffffffffe
0x00007FF776D110D3  488D542430               LEA       RDX, [RSP+0x30]                RDX=0x7bd673f880
0x00007FF776D110D8  FF15420F0000             CALL      GetThreadContext               RAX=0x1 RCX=0x7ff99ad5cf00 "eH" PSbaeGaw.dll RDX=0 R8=0x7bd673f648 R9=0xb7 R10=0x7ff99ad5cf00 "eH" PSbaeGaw.dll R11=0x7bd673f810 Xmm0.Low=0xa0c Xmm0.High=0x5e0 Xmm1.Low=0 Xmm1.High=0 P
0x00007FF776D110DE  85C0                     TEST      EAX, EAX                       p
0x00007FF776D110E0  7505                     JNZ       0x00007FF776D110E7            
0x00007FF776D110E7  48837C247800             CMP       QWORD [RSP+0x78], 0x0          PZ
0x00007FF776D110ED  7528                     JNZ       0x00007FF776D11117            
0x00007FF776D110EF  4883BC248000000000       CMP       QWORD [RSP+0x80], 0x0         
0x00007FF776D110F8  751D                     JNZ       0x00007FF776D11117            
0x00007FF776D110FA  4883BC248800000000       CMP       QWORD [RSP+0x88], 0x0         
0x00007FF776D11103  7512                     JNZ       0x00007FF776D11117            
0x00007FF776D11105  4883BC249000000000       CMP       QWORD [RSP+0x90], 0x0         
0x00007FF776D1110E  7507                     JNZ       0x00007FF776D11117            
0x00007FF776D11110  BE01000000               MOV       ESI, 0x1                       RSI=0x1
0x00007FF776D11115  EB02                     JMP       0x00007FF776D11119 

trace.log

bp0=ep,depth=all,count=all

@cccs-mog
Copy link
Contributor Author

cccs-mog commented Oct 3, 2025

I was looking at creating something for testing all the use cases from that checkpoint website and then realised that they already have a repo for that: https://github.com/CheckPointSW/showstopper/tree/master The next step would be to check the techniques against capemon to see if there is other point that could be improved. Looking into doing this and making a new commit with the findings. PR have been opened for quite a while and now have conflicts so will look at this as well.

@cccs-mog
Copy link
Contributor Author

cccs-mog commented Oct 3, 2025

Those two techniques are reliably detected by the script:

  1. https://anti-debug.checkpoint.com/techniques/assembly.html#instruction-counting
  2. https://anti-debug.checkpoint.com/techniques/misc.html#parent-process-check-ntqueryinformationprocess

I can provide the zip_compound I have used to execute the test if wanted.
The fix for 2 should be easy enough to addn but there seem to be no viable fix for 1 however.

There could be more as there is a few options to test and setup that I might be missing.

@kevoreilly
Copy link
Owner

Yes please do share the test zip!

I am intrigued by 1 - did your tests included just running this normally or tracing it using cape's debugger?

@cccs-mog
Copy link
Contributor Author

cccs-mog commented Oct 3, 2025

ShowStopper_compound.zip
Just running it normally for now with the differents flags for it https://github.com/CheckPointSW/showstopper/blob/master/DOCS.md. Planning on testing it while tracing it and/or in different context next week !

@kevoreilly
Copy link
Owner

Thank you for bringing this to my attention - it had occurred to me before that the debug register 'protection' code in the get and set thread context hook handlers was too basic - the ShowStopper instruction count check detection was due to this. I have improved the code now to only hide/protect debug registers if they contain 'internal' breakpoints: ed158f8 - so this check should no longer fail.

The only remaining check is due to the fact that the analyzer creates the initial process rather than the explorer shell. This can be worked around by manual launch in interactive mode. I previously worked on solving this problem a few years ago by attempting to implement the 'select my parent' technique publicised by Didier Stevens: https://blog.didierstevens.com/2009/11/22/quickpost-selectmyparent-or-playing-with-the-windows-process-tree/

I have this code working in C in the loader (https://github.com/kevoreilly/capemon/blob/capemon/loader/loader/Loader.c#L1541) but sadly failed to get it working in Python in lib/api/process.py - it might well be worth me having another crack at doing this now that we have LLMs to help...

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.

3 participants