Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
171 commits
Select commit Hold shift + click to select a range
18d3d00
Sleep skipping: ensure time_skipped variable is only used when sleep_…
kevoreilly Dec 17, 2024
322c30b
CoGetClassObject hook: add inspect_clsid for improved injection (e.g.…
kevoreilly Dec 17, 2024
e67164a
SetFileInformationByHandle hook
kevoreilly Dec 17, 2024
0f8eb92
GetComputerNameExW hook: add fake results for all NameTypes (e.g. 805…
kevoreilly Dec 17, 2024
f9183ca
ntapi.h: expanded SYSTEM_PROCESS_INFORMATION struct definition
kevoreilly Dec 17, 2024
6013d26
Initial commit for WMI hooks
KillerInstinct Feb 17, 2025
3a8a975
Merge pull request #86 from KillerInstinct/wmi_hooks
kevoreilly Feb 17, 2025
5e5f9a0
Perform WMI function lookups via yara
kevoreilly Feb 20, 2025
a8ec18f
Hook CryptDuplicateKey
KillerInstinct Apr 9, 2025
765e939
Merge pull request #93 from KillerInstinct/hook_CryptDuplicateKey
kevoreilly Apr 11, 2025
5e74ae4
Loader: add basic loader snaps capture ('snaps' parameter)
kevoreilly Apr 11, 2025
ee56e86
Loader: enable loader snaps in remote process via NtGlobalFlags
kevoreilly Apr 11, 2025
706e973
Loader: small correction in EnableLoaderSnaps debug output
kevoreilly Apr 11, 2025
98afb82
Loader: make GetNtGlobalFlagsOffset() work on 32-bit as well as 64-bit
kevoreilly Apr 14, 2025
92b1fa7
Native hookset (ntdll only) option: native=1
kevoreilly Apr 16, 2025
1b6396d
Hooking: 64-bit push-ret hook-type (hook-type=push-ret), low (<2GB) t…
kevoreilly Apr 16, 2025
67e800a
Disable AMSI dumps by default (also see previous commit)
kevoreilly Apr 16, 2025
4892e52
Improve log args for a few hooks:
KillerInstinct Apr 16, 2025
64de460
Fix autocomplete typos, tks Gemini
KillerInstinct Apr 16, 2025
ae60148
Windows Loader Snaps: vDbgPrintExWithPrefixInternal hook & option 'sn…
kevoreilly Apr 24, 2025
86f0619
.NET JIT cache dumps: off by default, configurable limit with option …
kevoreilly Apr 25, 2025
3208642
Remove obsolete function retarget_rip_relative_displacement() (hookin…
kevoreilly Apr 28, 2025
ddc1b4e
Remove obsolete function is_suspended() (misc.c)
kevoreilly Apr 28, 2025
df6dba6
Loader: fix Win7 compatibility, use WaitForDebugEvent instead of unav…
kevoreilly Apr 28, 2025
c98ddb8
Allow monitor to load without config ini file - defaults to standalon…
kevoreilly May 8, 2025
190d22d
Harden ScanForExport() function (used by GetExportNameByAddress())
kevoreilly May 14, 2025
fc9b8e5
Trace: switch from using ScyllaGetExportNameByAddress() to GetExportN…
kevoreilly May 14, 2025
30b5c86
Replace remaining uses of pipe("INFO:...) with DebugOutput()
kevoreilly May 19, 2025
ac31615
Define values for anti-analysis spoofing in hooks for consistency
kevoreilly May 22, 2025
36f03fc
Debugger: fix br1 (break on return) config option parsing (config.c)
kevoreilly May 23, 2025
f01664d
Trace: do not wrap GetExportNameByAddress() in try/catch and do not u…
kevoreilly May 23, 2025
2ff4187
Fix bug in retarget_relative_displacement() relative offset calculation
kevoreilly Jun 3, 2025
02fe0bd
Correction to previous commit - fix the bad fix
kevoreilly Jun 3, 2025
e627d57
Add comments to retarget_relative_displacement() (hooking_64.c)
kevoreilly Jun 4, 2025
31c7a34
Fix format string vulnerability in debugger StringsOutput() function
kevoreilly Jun 6, 2025
1bd2f23
Merge branch 'capemon' into wmi_hooks
kevoreilly Jun 6, 2025
5dc5c6e
Merge remote-tracking branch 'origin/capemon' into wmi_hooks
kevoreilly Jun 6, 2025
bbe1734
Merge pull request #96 from kevoreilly/wmi_hooks
kevoreilly Jun 6, 2025
de0e47d
WMI hooks: add handling for VT_NULL and enable WMI_Get logging
kevoreilly Jun 10, 2025
8ca9c56
Trace: don't print empty lines to strings output in DoOutputString()
kevoreilly Jun 25, 2025
6b66e54
Trace: add flag changes to trace output as part of OutputRegisterChan…
kevoreilly Jun 25, 2025
fe05e4f
Better NtDeviceIoControlFile logging for ntsockets
KillerInstinct Jul 14, 2025
b5b1349
Fix Gemini suggestions
KillerInstinct Jul 14, 2025
b2bb430
Improve NtGetContextThread & NtSetContextThread hooks to handle e.g. …
kevoreilly Jul 22, 2025
1ee2117
Improve standalone mode
meck-gd Jul 24, 2025
3271f81
Merge pull request #101 from GDATAAdvancedAnalytics/improve-standalon…
kevoreilly Jul 25, 2025
b8a974b
Improvements to NtGetContextThread & NtSetContextThread hooks in ligh…
kevoreilly Jul 25, 2025
61b243c
Merge branch 'logging_improvements' of https://github.com/KillerInsti…
kevoreilly Jul 25, 2025
8c58f4a
Fix missing ProcessMessage() from recently updated SetThreadContextHa…
kevoreilly Jul 31, 2025
11c0e05
Create DumpStrings debugger action for corresponding function
kevoreilly Aug 1, 2025
2784978
Enhance dynamic patching capability: new PatchBytes() function, submi…
kevoreilly Aug 1, 2025
a923abb
Initial support for hooking FindFixAndRun in cmd.exe
KillerInstinct Aug 12, 2025
1afaea8
Fixes for stuff from Gemini
KillerInstinct Aug 12, 2025
bd7aab2
Merge branch 'hook_FindFixAndRun' of https://github.com/KillerInstinc…
kevoreilly Aug 12, 2025
54f0328
Fix internal WMI_GetObjectAsync yara
kevoreilly Aug 12, 2025
998f89a
YaraHarness: fix issue with ParseOptionLine() adding imagebase to sys…
kevoreilly Aug 18, 2025
91120f8
YaraHarness: ensure YaraCallback calls SetInitialBreakpoints() for sy…
kevoreilly Aug 18, 2025
1ca0a99
FindFixAndRun hook: adapt to yara-based function address lookup with …
kevoreilly Aug 19, 2025
5fbd0cd
Merge branch 'capemon' into hook_FindFixAndRun
kevoreilly Aug 19, 2025
135d874
FindFixAndRun hook: remove ArgType from logging
kevoreilly Aug 19, 2025
8aea1eb
Add new hook for MapFileAndCheckSumA
enzok Aug 20, 2025
517cbed
Added hook for GetPwrCapabilities to bypass power_capabilities (al-kh…
mhdo298 Aug 21, 2025
d4aa770
Update hook_power.c for more accurate anti-anti-vm measures
mhdo298 Aug 22, 2025
d9cd7cf
Update hook_power.c
mhdo298 Aug 22, 2025
27a7d3d
Moved hook declaration to misc hooks
mhdo298 Aug 22, 2025
04d21b3
Moved hook declaration to misc hooks
mhdo298 Aug 22, 2025
1e84647
Fix GetMinPESize() parameter (PIMAGE_DOS_HEADER)
kevoreilly Aug 22, 2025
d4781c0
Changed according to comments
mhdo298 Aug 22, 2025
eda5cc8
Moved back
mhdo298 Aug 22, 2025
c2e8fdd
Update hooks.h
mhdo298 Aug 22, 2025
438141a
Remove Scylla code preventing dumping of MEW executables (fixes #106)
kevoreilly Aug 26, 2025
b52cb56
FindFixAndRun hook: improve FindFixAndRun yara signatures
kevoreilly Aug 26, 2025
5010878
hook_api (64-bit): test h->library before deref (exe hooks)
kevoreilly Aug 26, 2025
8307b50
Update hook_misc.c
mhdo298 Aug 26, 2025
883d1c9
Added hook for NtPowerInformation
mhdo298 Aug 26, 2025
158e745
Added more information to logging
mhdo298 Aug 26, 2025
de93e68
Merge pull request #103 from KillerInstinct/hook_FindFixAndRun
kevoreilly Aug 27, 2025
ed03bb7
Merge branch 'capemon' into capemon
mhdo298 Aug 28, 2025
9386ab8
Update hooks.c
mhdo298 Aug 28, 2025
10cead2
Add 'hook watch' feature to log hooks encountered (even if not execut…
kevoreilly Aug 28, 2025
2a41c63
Fix logging bug in NtReadVirtualMemory hook
kevoreilly Aug 28, 2025
c73909c
Fix logging bug in NtWriteVirtualMemory hook
kevoreilly Aug 28, 2025
f18dd16
Removed GetPwrCapabilities Hook
mhdo298 Aug 28, 2025
210ab9c
Removed GetPwrCapabilities Hook
mhdo298 Aug 28, 2025
33e78ec
Removed hook and added more checks
mhdo298 Aug 28, 2025
45e08a8
AddTrackedRegion: remove unnecessary logging (CAPE.c)
kevoreilly Aug 28, 2025
b318e5f
CoCreateInstance hook: remove disable_sleep_skip() breaking e.g. 493b…
kevoreilly Sep 1, 2025
cd9307d
Loader: use NewImportDirectorySize for patched import directory size …
kevoreilly Sep 2, 2025
cf1f75f
Merge branch 'capemon' into ntsockets
kevoreilly Sep 8, 2025
cc9d17f
Merge branch 'capemon' into patch-01
enzok Sep 9, 2025
cc2e89e
Update hook_misc.c
enzok Sep 9, 2025
41cf95c
MapFileAndCheckSumA hook: add more pointer checks (hook_misc.c)
kevoreilly Sep 10, 2025
48fc21d
Merge pull request #108 from enzok/patch-01
kevoreilly Sep 11, 2025
0e61188
Merge pull request #99 from KillerInstinct/ntsockets
kevoreilly Sep 11, 2025
e2064d1
Merge branch 'capemon' into capemon
kevoreilly Sep 11, 2025
38b8d53
Merge pull request #105 from mhdo298/capemon
kevoreilly Sep 11, 2025
0d875bd
Fix indentation in CAPE.c
kevoreilly Sep 15, 2025
ff4fba9
minhook: make hook order more consistent with full hookset
kevoreilly Sep 17, 2025
befd5ef
Merge branch 'capemon' of https://github.com/kevoreilly/capemon into …
kevoreilly Sep 17, 2025
d5415c9
Enhance VerifyHeaders() to include EP bytes to detect shellcode overw…
kevoreilly Sep 18, 2025
3503aab
Merge branch 'capemon' of https://github.com/kevoreilly/capemon into …
kevoreilly Sep 22, 2025
273bdc8
Tweak tracking of regions from syscall capture (InstrCallback.c)
kevoreilly Sep 22, 2025
cc8e0ce
Trace: don't step over named exported functions if trace-all set
kevoreilly Sep 22, 2025
beb1946
config: fix issue parsing multiple sysbp addresses supplied via submi…
kevoreilly Sep 22, 2025
de07473
unhook: attempt restoration of detected hook modifications
kevoreilly Sep 22, 2025
2ad14bf
Add ProcessParameters -> DllPath to log output for NtCreateUserProces…
kevoreilly Sep 23, 2025
e2cfeff
Add hook_restore option to enable/disable recently added hook restora…
kevoreilly Sep 26, 2025
c9b8830
Add some function patterns for Win11 24H2
meck-gd Sep 29, 2025
0f18be1
Merge pull request #109 from GDATAAdvancedAnalytics/fix-win11-24h2
kevoreilly Oct 1, 2025
e5dda18
Merge branch 'capemon' of https://github.com/kevoreilly/capemon into …
kevoreilly Oct 3, 2025
8fdc755
Fix issue with hook_restore config setting being ignored
kevoreilly Oct 3, 2025
ed158f8
Improve debugger breakpoint protection: fixes instruction counting an…
kevoreilly Oct 6, 2025
1dbb0b1
Fix bugs in GetFunctionByName() (thanks @heck-gd)
kevoreilly Oct 8, 2025
04387f3
Further improvements to GetFunctionByName() - thanks @heck-gd
kevoreilly Oct 8, 2025
758f68b
Include `<unordered_map>` instead of `<hash_map>`.
StephanTLavavej Oct 8, 2025
7f445f4
Use `std::unordered_multimap` instead of `stdext::hash_multimap`.
StephanTLavavej Oct 8, 2025
077fd91
Fix: Use `unordered_multimap::iterator` instead of `hash_map::iterator`.
StephanTLavavej Oct 8, 2025
11fe56c
Remove `_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS`.
StephanTLavavej Oct 8, 2025
fe3289c
Trace: fix issue with long conditional jump target calculation in Ins…
kevoreilly Oct 9, 2025
663b0f4
GetFunctionByName: break out of loop for efficiency
kevoreilly Oct 10, 2025
6d3405d
Expand 'DumpImage' debugger action to handle target imagebase address…
kevoreilly Oct 13, 2025
5011d49
Fix debug output for dump-limit config setting
kevoreilly Oct 13, 2025
e8ffb95
Fix cast for 64-bit debug registers in get/set thread context handlers
kevoreilly Oct 14, 2025
75984e9
Improve NtContinueHandler debug register stealth/protection to allow …
kevoreilly Oct 14, 2025
5ca5ec7
Merge pull request #111 from StephanTLavavej/unordered_map
kevoreilly Oct 15, 2025
5b0b58c
Implement Gemini suggestions from #111
kevoreilly Oct 15, 2025
a0fa612
Deprecate Win7 wow64 breakpoint workaround
kevoreilly Oct 15, 2025
740ca87
YaraHarness: simplify 'dump' option
kevoreilly Oct 20, 2025
441abea
YaraHarness: write rules canary detection to analysis log
kevoreilly Oct 20, 2025
46eb93b
Experimental debugger action 'guard' to trap on guard violation
kevoreilly Oct 22, 2025
e448954
Cap per-process messages to prevent detonation slow-down & failure in…
kevoreilly Oct 22, 2025
8b9cd28
Remove obsolete 'suspended' parameter from PROCESS monitor message
kevoreilly Oct 22, 2025
db61173
WriteMemoryHandler: prevent analysis log spam for small PE writes
kevoreilly Oct 22, 2025
2d82cd5
Apply update to PROCESS: monitor message in loader CreateMonitorPipe()
kevoreilly Oct 24, 2025
173d144
Deprecate ScyllaGetExportDirectory & ScyllaGetExportNameByScan, add G…
kevoreilly Oct 24, 2025
509ba73
Add exported function name logging to thread hooks: NtCreateThreadEx,…
kevoreilly Oct 24, 2025
6498c3d
Harden our_stackwalk() against invalid stack pointers (hooking_64)
kevoreilly Oct 28, 2025
9246186
Tweak KiUserExceptionDispatcher variable name to remove underscore
kevoreilly Oct 28, 2025
ad0557e
Fix/improve exception handling code which queries current SEH handler
kevoreilly Oct 28, 2025
d9bdb29
Fix KiUserExceptionDispatcher pointer type
kevoreilly Oct 28, 2025
15cd125
path_from_object_attributes(): fix issue with memcpy from bad ObjectN…
kevoreilly Nov 6, 2025
6703aff
hook_create_pre_tramp_notail(): Improve assembly comments (hooking_64)
kevoreilly Nov 7, 2025
4d5dbd1
CAPEExceptionFilter: refine anomaly logging (Debugger)
kevoreilly Nov 7, 2025
d408eea
Trace: remove obsolete global variables
kevoreilly Nov 7, 2025
e1ba2ff
Add config option for monitor injection into supplied pid or "explore…
kevoreilly Nov 17, 2025
1de5cf8
Trace: fix issue with depth count being incremented when stepping ove…
kevoreilly Nov 21, 2025
bf3b0dc
Replace BreakOnNtContinue as global variable (not extern)
kevoreilly Nov 24, 2025
0895638
Fix issue with RESUME: monitor message from NtResumeProcess hook
kevoreilly Nov 24, 2025
b362bd6
Setbp debugger actions: don't attempt to detect RVA and add imagebase
kevoreilly Nov 28, 2025
46b2bdd
ScyllaDumpProcess: fix entry point value in logs (RVA->VA)
kevoreilly Dec 2, 2025
08d2218
YaraHarness: prioritise internal sigs & capemon canary to load/scan f…
kevoreilly Dec 3, 2025
6703c55
Debugger: simplify ClearAllBreakpoints()
kevoreilly Dec 4, 2025
1b72bb0
RtlWow64SetThreadContext hook, Wow64 get/set handlers
kevoreilly Dec 4, 2025
c43ec20
RtlUserThreadStart hook
kevoreilly Dec 5, 2025
009c597
Add get_module_name() function
kevoreilly Dec 5, 2025
3233865
Hooking: replace (allocating) convert_address_to_dll_name_and_offset(…
kevoreilly Dec 5, 2025
5a87691
Add general hook protection (hook-protect=1) to protect hooks other t…
kevoreilly Dec 5, 2025
ef26a3a
Add ntdll unhook protection (ntdll-unhook=1) via prevent_module_unhoo…
kevoreilly Dec 9, 2025
f31bcf4
WTGetSignatureInfo hook - thanks @KillerInstinct
kevoreilly Dec 9, 2025
a9c2350
LdrGetDllHandleEx hook
kevoreilly Dec 9, 2025
46a8e2a
Couple new thread hooks
KillerInstinct Dec 12, 2025
d08ef21
K32EnumProcesses, WTSEnumerateProcessesW & WTSEnumerateProcessesExW h…
kevoreilly Dec 12, 2025
fc51646
Merge pull request #114 from KillerInstinct/hook_detect_rust
kevoreilly Dec 12, 2025
2bbb68a
GetPhysicallyInstalledSystemMemory hook
kevoreilly Dec 12, 2025
ba960db
misc: prevent_module_unhooking() & gettib()
kevoreilly Dec 12, 2025
ddf4961
hook_misc: use SPOOFED_RAM define rather than constants in memory que…
kevoreilly Dec 12, 2025
6da7bd7
Correct previous blundered commit
kevoreilly Dec 12, 2025
c820653
Add capesolo
enzok Dec 17, 2025
21d41be
Add interactive breakpoint support and string formatting
enzok Dec 17, 2025
8ddd7a0
Remove _pipe_sprintf declaration from Trace.c
enzok Dec 17, 2025
a06e16d
Refactor _NtQueryInformationThread declaration
enzok Dec 18, 2025
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
488 changes: 328 additions & 160 deletions CAPE/CAPE.c

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions CAPE/CAPE.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ PVOID GetAllocationBase(PVOID Address);
SIZE_T GetRegionSize(PVOID Address);
SIZE_T GetAllocationSize(PVOID Address);
SIZE_T GetAccessibleSize(PVOID Address);
PVOID GetFunctionByName(HMODULE ModuleBase, PCHAR FunctionName);
PVOID GetFunctionAddress(HMODULE ModuleBase, PCHAR FunctionName);
BOOL IsAddressAccessible(PVOID Address);
BOOL IsAddressExecutable(PVOID Address);
BOOL TestPERequirements(PIMAGE_NT_HEADERS pNtHeader);
SIZE_T GetMinPESize(PIMAGE_NT_HEADERS pNtHeader);
SIZE_T GetMinPESize(PIMAGE_DOS_HEADER pDosHeader);
double GetEntropy(PUCHAR Buffer);
void SanitiseString(char *Dst, const char *Src, size_t Size);
PCHAR TranslatePathFromDeviceToLetter(PCHAR DeviceFilePath);
Expand Down Expand Up @@ -77,9 +78,10 @@ int DumpImageInCurrentProcess(PVOID ImageBase);
void DumpSectionViewsForPid(DWORD Pid);
BOOL DumpRange(PVOID Address, SIZE_T Size);
BOOL DumpStackRegion(void);
void DumpStrings(void);

BOOL ProcessDumped;
unsigned int DumpCount;
unsigned int DumpCount, DotNetCacheDumpCount;

SYSTEM_INFO SystemInfo;
PVOID CallingModule;
Expand Down
226 changes: 57 additions & 169 deletions CAPE/Debugger.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,21 @@ extern char *convert_address_to_dll_name_and_offset(ULONG_PTR addr, unsigned int
extern PCHAR GetNameBySsn(unsigned int Number);
extern void log_direct_syscall(const char *function, PVOID addr);
extern unsigned int address_is_in_stack(DWORD Address);
extern BOOL WoW64fix(void);
extern BOOL WoW64PatchBreakpoint(unsigned int Register);
extern BOOL WoW64UnpatchBreakpoint(unsigned int Register);
extern BOOL SetInitialBreakpoints(PVOID ImageBase), Trace(struct _EXCEPTION_POINTERS* ExceptionInfo), SoftwareBreakpointCallback(struct _EXCEPTION_POINTERS* ExceptionInfo);
extern BOOL BreakpointCallback(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo);
extern BOOL GuardPageCallback(struct _EXCEPTION_POINTERS* ExceptionInfo);
extern void DebuggerOutput(_In_ LPCTSTR lpOutputString, ...), DoTraceOutput(PVOID Address);
extern BOOL TraceRunning, BreakpointsSet, BreakpointsHit, StopTrace, BreakOnNtContinue, SyscallBreakpointSet;
extern BOOL TraceRunning, BreakpointsSet, BreakpointsHit, StopTrace, SyscallBreakpointSet;
extern PVECTORED_EXCEPTION_HANDLER SampleVectoredHandler;
extern int StepOverRegister;
extern int process_shutting_down;
extern HANDLE DebuggerLog;
extern PVOID GuardedPages;

struct ThreadBreakpoints *MainThreadBreakpointList;
unsigned int TrapIndex, DepthCount;
PVOID _KiUserExceptionDispatcher;
BOOL SetSingleStepMode(PCONTEXT Context, PVOID Handler), ClearSingleStepMode(PCONTEXT Context);
PVOID KiUserExceptionDispatcher;
BOOL BreakOnNtContinue, SetSingleStepMode(PCONTEXT Context, PVOID Handler), ClearSingleStepMode(PCONTEXT Context);
lookup_t SoftBPs, SyscallBPs;
SOFTBP SyscallBP;

Expand Down Expand Up @@ -104,32 +103,43 @@ HANDLE GetThreadHandle(DWORD ThreadId)
}

//**************************************************************************************
BOOL PatchByte(LPVOID Address, BYTE Byte)
BOOL PatchBytes(LPVOID Address, const char* HexBytes)
//**************************************************************************************
{
DWORD OldProtect;
if (!Address || !HexBytes || !IsAddressAccessible(Address))
{
DebugOutput("PatchBytes: Invalid address or hex string");
return FALSE;
}

if (!Address || !IsAddressAccessible(Address))
return FALSE;
SIZE_T HexLen = strlen(HexBytes);
if (HexLen == 0 || HexLen % 2 != 0)
{
DebugOutput("PatchBytes: Invalid hex string length %d", HexLen);
return FALSE;
}

if (!VirtualProtect(Address, 1, PAGE_EXECUTE_READWRITE, &OldProtect))
SIZE_T ByteCount = HexLen / 2;
DWORD OldProtect;
if (!VirtualProtect(Address, ByteCount, PAGE_EXECUTE_READWRITE, &OldProtect))
{
DebugOutput("PatchByte: Unable to change memory protection at 0x%p", Address);
return FALSE;
}
DebugOutput("PatchBytes: Failed to change memory protection at 0x%p", Address);
return FALSE;
}

#ifdef DEBUG_COMMENTS
DebugOutput("PatchByte: Changed memory protection at 0x%p", Address);
#endif
PBYTE Dest = (PBYTE)Address;
for (SIZE_T i = 0; i < HexLen; i += 2)
{
char HexByte[3] = { HexBytes[i], HexBytes[i + 1], '\0' };
BYTE Byte = (BYTE)strtoul(HexByte, NULL, 16);
*Dest++ = Byte;
}

*(PBYTE)Address = Byte;
VirtualProtect(Address, ByteCount, OldProtect, &OldProtect);

#ifdef DEBUG_COMMENTS
DebugOutput("PatchByte: New instruction byte at 0x%p: 0x%x", Address, *(PBYTE)Address);
#endif
VirtualProtect(Address, 1, OldProtect, &OldProtect);
DebugOutput("PatchBytes: Patched %zu bytes at 0x%p: %s", ByteCount, Address, HexBytes);

return TRUE;
return TRUE;
}

//**************************************************************************************
Expand Down Expand Up @@ -496,7 +506,7 @@ BOOL SyscallBreakpointHandler(struct _EXCEPTION_POINTERS* ExceptionInfo)
}
#ifdef DEBUG_COMMENTS
else
DebugOutput("SyscallBreakpointHandler: Calling SSN 0x%x -> 0x%p: %s\n", SSN, Function, FunctionName);
DebugOutput("SyscallBreakpointHandler: Syscall at 0x%p, SSN 0x%x -> 0x%p: %s\n", ExceptionInfo->ExceptionRecord->ExceptionAddress, SSN, Function, FunctionName);
#endif

log_direct_syscall(FunctionName, (PVOID)CIP);
Expand Down Expand Up @@ -603,85 +613,31 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)

if (bp == 0 && ((DWORD_PTR)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr0))
{
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp0 address (0x%p) different to BreakpointInfo (0x%x)!\n", ExceptionInfo->ContextRecord->Dr0, pBreakpointInfo->Address);
if (pBreakpointInfo->Address)
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp0 address 0x%p different to internal breakpoint 0x%p\n", ExceptionInfo->ContextRecord->Dr0, pBreakpointInfo->Address);
return EXCEPTION_CONTINUE_SEARCH;
}

if (bp == 1 && ((DWORD_PTR)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr1))
{
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp1 address (0x%p) different to BreakpointInfo (0x%x)!\n", ExceptionInfo->ContextRecord->Dr1, pBreakpointInfo->Address);
if (pBreakpointInfo->Address)
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp1 address 0x%p different to internal breakpoint 0x%p\n", ExceptionInfo->ContextRecord->Dr1, pBreakpointInfo->Address);
return EXCEPTION_CONTINUE_SEARCH;
}

if (bp == 2 && ((DWORD_PTR)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr2))
{
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp2 address (0x%p) different to BreakpointInfo (0x%x)!\n", ExceptionInfo->ContextRecord->Dr2, pBreakpointInfo->Address);
if (pBreakpointInfo->Address)
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp2 address 0x%p different to internal breakpoint 0x%p\n", ExceptionInfo->ContextRecord->Dr2, pBreakpointInfo->Address);
return EXCEPTION_CONTINUE_SEARCH;
}

if (bp == 3 && ((DWORD_PTR)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr3))
{
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp3 address (0x%p) different to BreakpointInfo (0x%x)!\n", ExceptionInfo->ContextRecord->Dr3, pBreakpointInfo->Address);
if (pBreakpointInfo->Address)
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp3 address 0x%p different to internal breakpoint 0x%p\n", ExceptionInfo->ContextRecord->Dr3, pBreakpointInfo->Address);
return EXCEPTION_CONTINUE_SEARCH;
}
#ifndef _WIN64
if (bp == 0 && ((DWORD_PTR)pBreakpointInfo->Type != ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE0))
{
if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE0 == BP_WRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
{
DebugOutput("CAPEExceptionFilter: Reinstated BP_READWRITE on breakpoint %d (WoW64 workaround)\n", pBreakpointInfo->Register);

ContextSetThreadBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->HitCount, pBreakpointInfo->Callback);
}
else
{
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp0 type (0x%x) different to BreakpointInfo (0x%x)!\n", ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE0, pBreakpointInfo->Type);
CheckDebugRegisters(0, ExceptionInfo->ContextRecord);
}
}
if (bp == 1 && ((DWORD)pBreakpointInfo->Type != ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE1))
{
if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE1 == BP_WRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
{
DebugOutput("CAPEExceptionFilter: Reinstated BP_READWRITE on breakpoint %d (WoW64 workaround)\n", pBreakpointInfo->Register);

ContextSetThreadBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->HitCount, pBreakpointInfo->Callback);
}
else
{
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp1 type (0x%x) different to BreakpointInfo (0x%x)!\n", ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE1, pBreakpointInfo->Type);
CheckDebugRegisters(0, ExceptionInfo->ContextRecord);
}
}
if (bp == 2 && ((DWORD)pBreakpointInfo->Type != ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE2))
{
if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE2 == BP_WRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
{
DebugOutput("CAPEExceptionFilter: Reinstated BP_READWRITE on stack breakpoint %d (WoW64 workaround)\n", pBreakpointInfo->Register);

ContextSetThreadBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->HitCount, pBreakpointInfo->Callback);
}
else
{
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp2 type (0x%x) different to BreakpointInfo (0x%x)!\n", ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE2, pBreakpointInfo->Type);
CheckDebugRegisters(0, ExceptionInfo->ContextRecord);
}
}
if (bp == 3 && ((DWORD)pBreakpointInfo->Type != ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE3))
{
if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE3 == BP_WRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
{
DebugOutput("CAPEExceptionFilter: Reinstated BP_READWRITE on breakpoint %d (WoW64 workaround)\n", pBreakpointInfo->Register);

ContextSetThreadBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->HitCount, pBreakpointInfo->Callback);
}
else
{
DebugOutput("CAPEExceptionFilter: Anomaly detected! bp3 type (0x%x) different to BreakpointInfo (0x%x)!\n", ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE3, pBreakpointInfo->Type);
CheckDebugRegisters(0, ExceptionInfo->ContextRecord);
}
}
#endif // !_WIN64

if (pBreakpointInfo->HitCount)
{
Expand Down Expand Up @@ -810,6 +766,14 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
#endif
#endif
}
else if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
{
#ifdef DEBUG_COMMENTS
DebugOutput("CAPEExceptionFilter: Guard page violation at 0x%p\n", ExceptionInfo->ExceptionRecord->ExceptionAddress);
#endif
if (GetAllocationBase(ExceptionInfo->ExceptionRecord->ExceptionAddress) == GuardedPages && GuardPageCallback(ExceptionInfo))
return EXCEPTION_CONTINUE_EXECUTION;
}

// Exceptions in capemon
if ((ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress >= g_our_dll_base && (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress < (g_our_dll_base + g_our_dll_size))
Expand Down Expand Up @@ -917,11 +881,6 @@ BOOL ContextSetDebugRegisterEx
if (Type == BP_EXEC)
Length = 0;

#ifndef _WIN64
if (Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)Address))
WoW64PatchBreakpoint(Register);
#endif

if (Register == 0)
{
*Dr0 = (DWORD_PTR)Address;
Expand Down Expand Up @@ -1063,11 +1022,6 @@ BOOL SetDebugRegister
if (Type == BP_EXEC)
Length = 0;

#ifndef _WIN64
if (Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)Address))
WoW64PatchBreakpoint(Register);
#endif

if (Register == 0)
{
*Dr0 = (DWORD_PTR)Address;
Expand Down Expand Up @@ -1264,59 +1218,8 @@ BOOL ContextClearAllBreakpoints(PCONTEXT Context)
BOOL ClearAllBreakpoints()
//**************************************************************************************
{
CONTEXT Context;
PTHREADBREAKPOINTS ThreadBreakpoints;
unsigned int Register;

ThreadBreakpoints = MainThreadBreakpointList;

while (ThreadBreakpoints)
{
if (!ThreadBreakpoints->ThreadId)
{
DebugOutput("ClearAllBreakpoints: Error: no thread id for thread breakpoints 0x%x.\n", ThreadBreakpoints);
return FALSE;
}

if (!ThreadBreakpoints->ThreadHandle)
{
DebugOutput("ClearAllBreakpoints: Error no thread handle for thread %d.\n", ThreadBreakpoints->ThreadId);
return FALSE;
}

for (Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
{
ThreadBreakpoints->BreakpointInfo[Register].Size = 0;
ThreadBreakpoints->BreakpointInfo[Register].Address = NULL;
ThreadBreakpoints->BreakpointInfo[Register].Type = 0;
ThreadBreakpoints->BreakpointInfo[Register].HitCount = 0;
ThreadBreakpoints->BreakpointInfo[Register].Callback = NULL;
}

memset(&Context, 0, sizeof(CONTEXT));
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;

Context.Dr0 = 0;
Context.Dr1 = 0;
Context.Dr2 = 0;
Context.Dr3 = 0;
Context.Dr6 = 0;
Context.Dr7 = 0;

if (!SetThreadContext(ThreadBreakpoints->ThreadHandle, &Context))
{
#ifdef DEBUG_COMMENTS
DebugOutput("ClearAllBreakpoints: Error setting thread context (thread %d).\n", ThreadBreakpoints->ThreadId);
#endif
return FALSE;
}
#ifdef DEBUG_COMMENTS
else
DebugOutput("ClearAllBreakpoints: Cleared breakpoints for thread %d (handle 0x%x).\n", ThreadBreakpoints->ThreadId, ThreadBreakpoints->ThreadHandle);
#endif

ThreadBreakpoints = ThreadBreakpoints->NextThreadBreakpoints;
}
for (unsigned int Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
ClearBreakpoint(Register);

ClearSoftwareBreakpoints();

Expand Down Expand Up @@ -1372,11 +1275,6 @@ BOOL ContextClearBreakpointEx(PCONTEXT Context, PBREAKPOINTINFO pBreakpointInfo,
Dr7->L3 = 0;
}

#ifndef _WIN64
if (pBreakpointInfo->Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
WoW64UnpatchBreakpoint(pBreakpointInfo->Register);
#endif

pBreakpointInfo->Address = 0;
pBreakpointInfo->Size = 0;
pBreakpointInfo->Type = 0;
Expand Down Expand Up @@ -1864,11 +1762,6 @@ BOOL ClearDebugRegister
Dr7->L3 = 0;
}

#ifndef _WIN64
if (Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)Address))
WoW64UnpatchBreakpoint(Register);
#endif

Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;

if (!SetThreadContext(hThread, &Context))
Expand Down Expand Up @@ -2736,27 +2629,22 @@ BOOL InitialiseDebugger(void)
}

// Store address of KiUserExceptionDispatcher
_KiUserExceptionDispatcher = GetProcAddress(GetModuleHandle("ntdll"), "KiUserExceptionDispatcher");
HMODULE ntdll = GetModuleHandle("ntdll");
KiUserExceptionDispatcher = GetProcAddress(ntdll, "KiUserExceptionDispatcher");

if (_KiUserExceptionDispatcher == NULL)
if (KiUserExceptionDispatcher == NULL)
{
DebugOutput("InitialiseDebugger error: could not resolve ntdll::KiUserExceptionDispatcher.\n");
return FALSE;
}
#ifdef DEBUG_COMMENTS
else DebugOutput("InitialiseDebugger: ntdll::KiUserExceptionDispatcher = 0x%p\n", _KiUserExceptionDispatcher);
else DebugOutput("InitialiseDebugger: ntdll::KiUserExceptionDispatcher = 0x%p\n", KiUserExceptionDispatcher);
#endif

// Initialise global variables
ChildProcessId = 0;
SingleStepHandler = NULL;

#ifndef _WIN64
// Ensure wow64 patch is installed if needed
if (!g_config.msi)
WoW64fix();
#endif

g_config.debugger = 1;
DebuggerInitialised = TRUE;

Expand Down Expand Up @@ -2802,7 +2690,7 @@ void NtContinueHandler(PCONTEXT ThreadContext)

TrackExecution(CIP);

if (BreakpointsSet)
if (g_config.debugger)
{
DWORD ThreadId = GetCurrentThreadId();
PTHREADBREAKPOINTS ThreadBreakpoints = GetThreadBreakpoints(ThreadId);
Expand Down
2 changes: 1 addition & 1 deletion CAPE/Debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ BOOL InitialiseDebugger(void);
BOOL ResumeFromBreakpoint(PCONTEXT Context);
void OutputThreadBreakpoints(DWORD ThreadId);
void DebugOutputThreadBreakpoints();
BOOL PatchByte(LPVOID Address, BYTE Byte);
BOOL PatchBytes(LPVOID Address, const char* HexBytes);

void ShowStack(DWORD_PTR StackPointer, unsigned int NumberOfRecords);

Expand Down
Loading