diff --git a/.gitignore b/.gitignore
index ffc88da..418e99b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,5 @@ Release
tests/logging-test.*
*.suo
*.opendb
-*.VC.db
\ No newline at end of file
+*.VC.db
+.vs/*
diff --git a/CAPE/CAPE.c b/CAPE/CAPE.c
index c6ffd91..8c27ae0 100644
--- a/CAPE/CAPE.c
+++ b/CAPE/CAPE.c
@@ -15,17 +15,19 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see .
*/
-#define _CRT_RAND_S
+#define _CRT_RAND_S
#define MD5LEN 16
#define MAX_PRETRAMP_SIZE 320
#define MAX_TRAMP_SIZE 128
+#define MAX_UNICODE_PATH 32768
-#define BUFSIZE 1024 // For hashing
-#define DUMP_MAX 100
+#define BUFSIZE 1024 // For hashing
+#define DUMP_MAX 100
#define CAPE_OUTPUT_FILE "CapeOutput.bin"
+#define SUSPENDED_THREAD_MAX 4096
-#include
+#include
#include
#include
#include
@@ -37,12 +39,14 @@ along with this program.If not, see .
#include
#include
#include
+#include
#include "CAPE.h"
#include "Debugger.h"
#include "..\alloc.h"
#include "..\pipe.h"
#include "..\config.h"
+#include "..\lookup.h"
#pragma comment(lib, "Shlwapi.lib")
@@ -101,11 +105,20 @@ typedef struct _hook_info_t {
ULONG_PTR parent_caller_retaddr;
} hook_info_t;
-static unsigned int DumpCount;
-
-extern uint32_t path_from_handle(HANDLE handle, wchar_t *path, uint32_t path_buffer_len);
+extern hook_t g_hooks[];
-#define CAPE_OUTPUT_FILE "CapeOutput.bin"
+extern uint32_t path_from_handle(HANDLE handle, wchar_t *path, uint32_t path_buffer_len);
+extern wchar_t *ensure_absolute_unicode_path(wchar_t *out, const wchar_t *in);
+extern int called_by_hook(void);
+extern int operate_on_backtrace(ULONG_PTR _esp, ULONG_PTR _ebp, void *extra, int(*func)(void *, ULONG_PTR));
+extern unsigned int address_is_in_stack(PVOID Address);
+extern hook_info_t *hook_info();
+extern ULONG_PTR base_of_dll_of_interest;
+extern wchar_t *our_process_path_w;
+extern wchar_t *our_commandline;
+extern ULONG_PTR g_our_dll_base;
+extern DWORD g_our_dll_size;
+extern lookup_t g_caller_regions;
extern void DoOutputDebugString(_In_ LPCTSTR lpOutputString, ...);
extern void DoOutputErrorString(_In_ LPCTSTR lpOutputString, ...);
@@ -116,26 +129,20 @@ extern int ScyllaDumpProcess(HANDLE hProcess, DWORD_PTR modBase, DWORD_PTR NewOE
extern int ScyllaDumpCurrentProcessFixImports(DWORD_PTR NewOEP);
extern int ScyllaDumpProcessFixImports(HANDLE hProcess, DWORD_PTR modBase, DWORD_PTR NewOEP);
extern int ScyllaDumpPE(DWORD_PTR Buffer);
+extern int ScyllaDumpPEToFileHandle(DWORD_PTR Buffer, HANDLE FileHandle);
+extern unsigned int ScyllaDumpProcessToFileHandle(HANDLE hProcess, DWORD_PTR ModuleBase, DWORD_PTR NewOEP, HANDLE FileHandle);
extern BOOL CountDepth(LPVOID* ReturnAddress, LPVOID Address);
extern SIZE_T GetPESize(PVOID Buffer);
-
-extern int operate_on_backtrace(ULONG_PTR _esp, ULONG_PTR _ebp, void *extra, int(*func)(void *, ULONG_PTR));
-extern unsigned int address_is_in_stack(PVOID Address);
-extern hook_info_t *hook_info();
-extern ULONG_PTR base_of_dll_of_interest;
-extern wchar_t *our_process_path;
-extern ULONG_PTR base_of_dll_of_interest;
-extern ULONG_PTR g_our_dll_base;
-extern DWORD g_our_dll_size;
-
-extern unsigned int address_is_in_stack(PVOID Address);
-static HMODULE s_hInst = NULL;
-static WCHAR s_wzDllPath[MAX_PATH];
-CHAR s_szDllPath[MAX_PATH];
-
-BOOL ProcessDumped;
-extern PVOID CallingModule;
extern LPVOID GetReturnAddress(hook_info_t *hookinfo);
+extern PVOID CallingModule;
+#ifdef CAPE_TRACE
+extern BOOL SetInitialBreakpoints(PVOID ImageBase);
+extern BOOL BreakpointsSet;
+#endif
+
+BOOL ProcessDumped, FilesDumped, ModuleDumped;
+static PVOID ImageBase;
+static unsigned int DumpCount;
static __inline ULONG_PTR get_stack_top(void)
{
@@ -154,8 +161,11 @@ static __inline ULONG_PTR get_stack_bottom(void)
return __readgsqword(0x10);
#endif
}
+
+CRITICAL_SECTION ProcessDumpCriticalSection;
+
//**************************************************************************************
-BOOL InsideHook(LPVOID* ReturnAddress, LPVOID Address)
+BOOL InsideMonitor(LPVOID* ReturnAddress, LPVOID Address)
//**************************************************************************************
{
if ((ULONG_PTR)Address >= g_our_dll_base && (ULONG_PTR)Address < (g_our_dll_base + g_our_dll_size))
@@ -164,7 +174,7 @@ BOOL InsideHook(LPVOID* ReturnAddress, LPVOID Address)
*ReturnAddress = Address;
return TRUE;
}
-
+
return FALSE;
}
@@ -185,16 +195,11 @@ LPVOID GetReturnAddress(hook_info_t *hookinfo)
__try
{
-#ifdef _WIN64
- DoOutputDebugString("GetReturnAddress: operate_on_backtrace call with Rip 0x%p.\n", hookinfo->frame_pointer);
-#else
- DoOutputDebugString("GetReturnAddress: operate_on_backtrace call with Ebp 0x%x.\n", hookinfo->frame_pointer);
-#endif
operate_on_backtrace(hookinfo->stack_pointer, hookinfo->frame_pointer, &ReturnAddress, GetCurrentFrame);
return ReturnAddress;
}
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
#ifdef _WIN64
DoOutputDebugString("GetReturnAddress: Exception trying to get return address with Rip 0x%p.\n", hookinfo->frame_pointer);
#else
@@ -205,33 +210,41 @@ LPVOID GetReturnAddress(hook_info_t *hookinfo)
}
//**************************************************************************************
-void GetHookCallerBase()
+PVOID GetHookCallerBase(hook_info_t *hookinfo)
//**************************************************************************************
{
PVOID ReturnAddress, AllocationBase;
+ if (!hookinfo)
+ {
+ DoOutputDebugString("GetHookCallerBase: hookinfo NULL.\n");
+ hookinfo = hook_info();
+ }
- if (CallingModule)
- return;
-
- ReturnAddress = GetReturnAddress(hook_info());
+ if (hookinfo->main_caller_retaddr)
+ ReturnAddress = (PVOID)hookinfo->main_caller_retaddr;
+ else if (hookinfo->parent_caller_retaddr)
+ ReturnAddress = (PVOID)hookinfo->parent_caller_retaddr;
+ //else
+ // ReturnAddress = GetReturnAddress(hookinfo);
if (ReturnAddress)
{
DWORD ThreadId = GetCurrentThreadId();
-
+
AllocationBase = GetAllocationBase(ReturnAddress);
DoOutputDebugString("GetHookCallerBase: thread %d (handle 0x%x), return address 0x%p, allocation base 0x%p.\n", ThreadId, GetThreadHandle(ThreadId), ReturnAddress, AllocationBase);
if (AllocationBase)
{
CallingModule = AllocationBase;
+ return CallingModule;
// Base-dependent breakpoints can be activated now
}
}
else
DoOutputDebugString("GetHookCallerBase: failed to get return address.\n");
- return;
+ return NULL;
}
//**************************************************************************************
@@ -239,15 +252,15 @@ void PrintHexBytes(__in char* TextBuffer, __in BYTE* HexBuffer, __in unsigned in
//**************************************************************************************
{
unsigned int i;
-
+
if (HexBuffer == NULL)
return;
-
+
for (i=0; iTargetPid = TargetPid;
-
+
if (CapeMetaData->TargetProcess == NULL)
{
DoOutputDebugString("SetCapeMetaData: failed to allocate memory for target process string.\n");
return FALSE;
}
-
+
if (CapeMetaData->TargetProcess == NULL && !GetModuleFileNameEx(hTargetProcess, NULL, CapeMetaData->TargetProcess, MAX_PATH))
{
CapeMetaData->TargetProcess = (char*)malloc(MAX_PATH);
@@ -432,7 +445,7 @@ BOOL MapFile(HANDLE hFile, unsigned char **Buffer, DWORD* FileSize)
{
LARGE_INTEGER LargeFileSize;
DWORD dwBytesRead;
-
+
if (!GetFileSizeEx(hFile, &LargeFileSize))
{
DoOutputErrorString("MapFile: Cannot get file size");
@@ -452,23 +465,23 @@ BOOL MapFile(HANDLE hFile, unsigned char **Buffer, DWORD* FileSize)
}
*FileSize = LargeFileSize.LowPart;
-
+
DoOutputDebugString("File size: 0x%x", *FileSize);
-
+
*Buffer = malloc(*FileSize);
-
+
if (SetFilePointer(hFile, 0, 0, FILE_BEGIN))
{
DoOutputErrorString("MapFile: Failed to set file pointer");
- return FALSE;
+ return FALSE;
}
-
+
if (*Buffer == NULL)
{
DoOutputErrorString("MapFile: Memory allocation error in MapFile");
return FALSE;
}
-
+
if (FALSE == ReadFile(hFile, (LPVOID)*Buffer, *FileSize, &dwBytesRead, NULL))
{
DoOutputErrorString("ReadFile error");
@@ -489,7 +502,7 @@ BOOL MapFile(HANDLE hFile, unsigned char **Buffer, DWORD* FileSize)
free(Buffer);
return FALSE;
}
-
+
return TRUE;
}
@@ -497,19 +510,19 @@ BOOL MapFile(HANDLE hFile, unsigned char **Buffer, DWORD* FileSize)
PINJECTIONINFO GetInjectionInfo(DWORD ProcessId)
//**************************************************************************************
{
- DWORD CurrentProcessId;
-
+ DWORD CurrentProcessId;
+
PINJECTIONINFO CurrentInjectionInfo = InjectionInfoList;
while (CurrentInjectionInfo)
{
CurrentProcessId = CurrentInjectionInfo->ProcessId;
-
+
if (CurrentProcessId == ProcessId)
return CurrentInjectionInfo;
else
CurrentInjectionInfo = CurrentInjectionInfo->NextInjectionInfo;
}
-
+
return NULL;
}
@@ -520,53 +533,53 @@ PINJECTIONINFO CreateInjectionInfo(DWORD ProcessId)
PINJECTIONINFO CurrentInjectionInfo, PreviousInjectionInfo;
PreviousInjectionInfo = NULL;
-
+
if (InjectionInfoList == NULL)
{
InjectionInfoList = ((struct InjectionInfo*)malloc(sizeof(struct InjectionInfo)));
-
+
if (InjectionInfoList == NULL)
{
DoOutputDebugString("CreateInjectionInfo: failed to allocate memory for initial injection info list.\n");
return NULL;
}
-
+
memset(InjectionInfoList, 0, sizeof(struct InjectionInfo));
-
+
InjectionInfoList->ProcessId = ProcessId;
}
CurrentInjectionInfo = InjectionInfoList;
-
+
while (CurrentInjectionInfo)
- {
+ {
if ((CurrentInjectionInfo->ProcessId) == ProcessId)
- break;
-
+ break;
+
PreviousInjectionInfo = CurrentInjectionInfo;
CurrentInjectionInfo = CurrentInjectionInfo->NextInjectionInfo;
}
-
+
if (!CurrentInjectionInfo)
{
// We haven't found it in the linked list, so create a new one
CurrentInjectionInfo = PreviousInjectionInfo;
-
+
CurrentInjectionInfo->NextInjectionInfo = ((struct InjectionInfo*)malloc(sizeof(struct InjectionInfo)));
-
+
if (CurrentInjectionInfo->NextInjectionInfo == NULL)
{
DoOutputDebugString("CreateInjectionInfo: Failed to allocate new thread breakpoints.\n");
return NULL;
}
-
+
memset(CurrentInjectionInfo->NextInjectionInfo, 0, sizeof(struct InjectionInfo));
-
+
CurrentInjectionInfo = CurrentInjectionInfo->NextInjectionInfo;
-
+
CurrentInjectionInfo->ProcessId = ProcessId;
}
-
+
return CurrentInjectionInfo;
}
@@ -575,7 +588,7 @@ PINJECTIONSECTIONVIEW GetSectionView(HANDLE SectionHandle)
//**************************************************************************************
{
PINJECTIONSECTIONVIEW CurrentSectionView = SectionViewList;
-
+
while (CurrentSectionView)
{
if (CurrentSectionView->SectionHandle == SectionHandle)
@@ -586,7 +599,7 @@ PINJECTIONSECTIONVIEW GetSectionView(HANDLE SectionHandle)
CurrentSectionView = CurrentSectionView->NextSectionView;
}
-
+
return NULL;
}
@@ -597,56 +610,56 @@ PINJECTIONSECTIONVIEW AddSectionView(HANDLE SectionHandle, PVOID LocalView, SIZE
PINJECTIONSECTIONVIEW CurrentSectionView, PreviousSectionView;
PreviousSectionView = NULL;
-
+
if (SectionViewList == NULL)
{
SectionViewList = ((struct InjectionSectionView*)malloc(sizeof(struct InjectionSectionView)));
-
+
if (SectionViewList == NULL)
{
DoOutputDebugString("AddSectionView: failed to allocate memory for initial section view list.\n");
return NULL;
}
-
+
memset(SectionViewList, 0, sizeof(struct InjectionSectionView));
-
+
SectionViewList->SectionHandle = SectionHandle;
SectionViewList->LocalView = LocalView;
SectionViewList->ViewSize = ViewSize;
}
CurrentSectionView = SectionViewList;
-
+
while (CurrentSectionView)
{
if ((CurrentSectionView->SectionHandle) == SectionHandle)
- break;
-
+ break;
+
PreviousSectionView = CurrentSectionView;
CurrentSectionView = CurrentSectionView->NextSectionView;
}
-
+
if (!CurrentSectionView)
{
// We haven't found it in the linked list, so create a new one
CurrentSectionView = PreviousSectionView;
-
+
CurrentSectionView->NextSectionView = ((struct InjectionSectionView*)malloc(sizeof(struct InjectionSectionView)));
-
+
if (CurrentSectionView->NextSectionView == NULL)
{
DoOutputDebugString("CreateSectionView: Failed to allocate new injection sectionview structure.\n");
return NULL;
}
-
+
memset(CurrentSectionView->NextSectionView, 0, sizeof(struct InjectionSectionView));
-
+
CurrentSectionView = CurrentSectionView->NextSectionView;
CurrentSectionView->SectionHandle = SectionHandle;
- CurrentSectionView->LocalView = LocalView;
- CurrentSectionView->ViewSize = ViewSize;
+ CurrentSectionView->LocalView = LocalView;
+ CurrentSectionView->ViewSize = ViewSize;
}
-
+
return CurrentSectionView;
}
@@ -657,7 +670,7 @@ BOOL DropSectionView(PINJECTIONSECTIONVIEW SectionView)
PINJECTIONSECTIONVIEW CurrentSectionView, PreviousSectionView;
PreviousSectionView = NULL;
-
+
if (SectionViewList == NULL)
{
DoOutputDebugString("DropSectionView: failed to obtain initial section view list.\n");
@@ -665,7 +678,7 @@ BOOL DropSectionView(PINJECTIONSECTIONVIEW SectionView)
}
CurrentSectionView = SectionViewList;
-
+
while (CurrentSectionView)
{
if (CurrentSectionView == SectionView)
@@ -686,16 +699,16 @@ BOOL DropSectionView(PINJECTIONSECTIONVIEW SectionView)
SectionViewList = NULL;
DoOutputDebugString("DropSectionView: removed the head of the section view list.\n");
}
-
+
free(CurrentSectionView);
-
- return TRUE;
+
+ return TRUE;
}
-
+
PreviousSectionView = CurrentSectionView;
CurrentSectionView = CurrentSectionView->NextSectionView;
}
-
+
return FALSE;
}
@@ -708,7 +721,7 @@ void DumpSectionViewsForPid(DWORD Pid)
DWORD BufferSize = MAX_PATH;
LPVOID PEPointer = NULL;
BOOL Dumped = FALSE;
-
+
CurrentInjectionInfo = GetInjectionInfo(Pid);
if (CurrentInjectionInfo == NULL)
@@ -724,13 +737,13 @@ void DumpSectionViewsForPid(DWORD Pid)
if (CurrentSectionView->TargetProcessId == Pid && CurrentSectionView->LocalView)
{
DoOutputDebugString("DumpSectionViewsForPid: Shared section view found with pid %d, local address 0x%p.\n", Pid);
-
+
PEPointer = CurrentSectionView->LocalView;
-
+
while (ScanForDisguisedPE(PEPointer, CurrentSectionView->ViewSize - ((DWORD_PTR)PEPointer - (DWORD_PTR)CurrentSectionView->LocalView), &PEPointer))
{
DoOutputDebugString("DumpSectionViewsForPid: Dumping PE image from shared section view, local address 0x%p.\n", PEPointer);
-
+
CapeMetaData->DumpType = INJECTION_PE;
CapeMetaData->TargetPid = Pid;
CapeMetaData->Address = PEPointer;
@@ -742,35 +755,35 @@ void DumpSectionViewsForPid(DWORD Pid)
}
else
DoOutputDebugString("DumpSectionViewsForPid: Failed to dump PE image from shared section view.\n");
-
+
((BYTE*)PEPointer)++;
}
-
+
if (Dumped == FALSE)
{
DoOutputDebugString("DumpSectionViewsForPid: no PE file found in shared section view, attempting raw dump.\n");
-
+
CapeMetaData->DumpType = INJECTION_SHELLCODE;
-
+
CapeMetaData->TargetPid = Pid;
-
+
if (DumpMemory(CurrentSectionView->LocalView, CurrentSectionView->ViewSize))
{
DoOutputDebugString("DumpSectionViewsForPid: Dumped shared section view.");
Dumped = TRUE;
}
else
- DoOutputDebugString("DumpSectionViewsForPid: Failed to dump shared section view.");
+ DoOutputDebugString("DumpSectionViewsForPid: Failed to dump shared section view.");
}
}
-
+
//DropSectionView(CurrentSectionView);
-
+
CurrentSectionView = CurrentSectionView->NextSectionView;
}
-
+
if (Dumped == FALSE)
- DoOutputDebugString("DumpSectionViewsForPid: no shared section views found for pid %d.\n", Pid);
+ DoOutputDebugString("DumpSectionViewsForPid: no shared section views found for pid %d.\n", Pid);
return;
}
@@ -782,7 +795,7 @@ void DumpSectionView(PINJECTIONSECTIONVIEW SectionView)
DWORD BufferSize = MAX_PATH;
LPVOID PEPointer = NULL;
BOOL Dumped = FALSE;
-
+
if (!SectionView->LocalView)
{
DoOutputDebugString("DumpSectionView: Section view local view address not set.\n");
@@ -794,95 +807,106 @@ void DumpSectionView(PINJECTIONSECTIONVIEW SectionView)
DoOutputDebugString("DumpSectionView: Section view has no target process - error.\n");
return;
}
-
+
Dumped = DumpPEsInRange(SectionView->LocalView, SectionView->ViewSize);
-
+
if (Dumped)
DoOutputDebugString("DumpSectionView: Dumped PE image from shared section view, local address 0x%p.\n", SectionView->LocalView);
else
{
DoOutputDebugString("DumpSectionView: no PE file found in shared section view, attempting raw dump.\n");
-
+
CapeMetaData->DumpType = INJECTION_SHELLCODE;
-
+
CapeMetaData->TargetPid = SectionView->TargetProcessId;
-
+
if (DumpMemory(SectionView->LocalView, SectionView->ViewSize))
{
DoOutputDebugString("DumpSectionView: Dumped shared section view.");
Dumped = TRUE;
}
else
- DoOutputDebugString("DumpSectionView: Failed to dump shared section view.");
+ DoOutputDebugString("DumpSectionView: Failed to dump shared section view.");
}
-
+
if (Dumped == TRUE)
DropSectionView(SectionView);
-
+
return;
}
//**************************************************************************************
-char* GetName()
+char* GetResultsPath(char* FolderName)
//**************************************************************************************
{
- char *OutputFilename, *FullPathName;
- SYSTEMTIME Time;
+ char *FullPath;
DWORD RetVal;
- unsigned int random;
-
- FullPathName = (char*) malloc(MAX_PATH);
- if (FullPathName == NULL)
+ FullPath = (char*)malloc(MAX_PATH);
+
+ if (FullPath == NULL)
{
- DoOutputErrorString("GetName: Error allocating memory for full path string");
- return 0;
+ DoOutputErrorString("GetResultsPath: Error allocating memory for full path string");
+ return 0;
}
-
+
+ // We want to dump output to the 'results' directory
+ memset(FullPath, 0, MAX_PATH);
+
+ strncpy_s(FullPath, MAX_PATH, g_config.results, strlen(g_config.results)+1);
+
+ if (strlen(FullPath) + 1 + strlen(FolderName) >= MAX_PATH)
+ {
+ DoOutputDebugString("GetResultsPath: Error, destination path too long.\n");
+ free(FullPath);
+ return 0;
+ }
+
+ PathAppend(FullPath, FolderName);
+
+ RetVal = CreateDirectory(FullPath, NULL);
+
+ if (RetVal == 0 && GetLastError() != ERROR_ALREADY_EXISTS)
+ {
+ DoOutputDebugString("GetResultsPath: Error creating output directory.\n");
+ free(FullPath);
+ return 0;
+ }
+
+ return FullPath;
+}
+
+//**************************************************************************************
+char* GetName()
+//**************************************************************************************
+{
+ char *FullPathName,*OutputFilename;
+ SYSTEMTIME Time;
+ unsigned int random;
+
+ FullPathName = GetResultsPath("CAPE");
+
OutputFilename = (char*)malloc(MAX_PATH);
-
+
if (OutputFilename == NULL)
{
- DoOutputErrorString("GetName: failed to allocate memory for file name string");
+ DoOutputErrorString("DumpMemory: failed to allocate memory for file name string");
return 0;
}
-
+
GetSystemTime(&Time);
-
+
if (rand_s(&random))
{
- DoOutputErrorString("GetName: failed to obtain a random number");
+ DoOutputErrorString("DumpMemory: failed to obtain a random number");
return 0;
}
-
- sprintf_s(OutputFilename, MAX_PATH*sizeof(char), "%d_%d%d%d%d%d%d%d%d", GetCurrentProcessId(), abs(random * Time.wMilliseconds), Time.wSecond, Time.wMinute, Time.wHour, Time.wDay, Time.wDayOfWeek, Time.wMonth, Time.wYear);
-
- // We want to dump CAPE output to the 'analyzer' directory
- memset(FullPathName, 0, MAX_PATH);
-
- strncpy_s(FullPathName, MAX_PATH, g_config.analyzer, strlen(g_config.analyzer)+1);
-
- if (strlen(FullPathName) + strlen("\\CAPE\\") + strlen(OutputFilename) >= MAX_PATH)
- {
- DoOutputDebugString("GetName: Error, CAPE destination path too long.");
- free(OutputFilename);
- free(FullPathName);
- return 0;
- }
-
- PathAppend(FullPathName, "CAPE");
- RetVal = CreateDirectory(FullPathName, NULL);
+ sprintf_s(OutputFilename, MAX_PATH*sizeof(char), "%d_%d%d%d%d%d%d%d%d", GetCurrentProcessId(), abs(random * Time.wMilliseconds), Time.wSecond, Time.wMinute, Time.wHour, Time.wDay, Time.wDayOfWeek, Time.wMonth, Time.wYear);
- if (RetVal == 0 && GetLastError() != ERROR_ALREADY_EXISTS)
- {
- DoOutputDebugString("GetName: Error creating output directory");
- free(OutputFilename);
- free(FullPathName);
- return 0;
- }
+ PathAppend(FullPathName, OutputFilename);
- PathAppend(FullPathName, OutputFilename);
+ free(OutputFilename);
return FullPathName;
}
@@ -907,14 +931,14 @@ BOOL GetHash(unsigned char* Buffer, unsigned int Size, char* OutputFilenameBuffe
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
- DoOutputErrorString("CryptCreateHash failed");
+ DoOutputErrorString("CryptCreateHash failed");
CryptReleaseContext(hProv, 0);
return 0;
}
if (!CryptHashData(hHash, Buffer, Size, 0))
{
- DoOutputErrorString("CryptHashData failed");
+ DoOutputErrorString("CryptHashData failed");
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
return 0;
@@ -923,17 +947,17 @@ BOOL GetHash(unsigned char* Buffer, unsigned int Size, char* OutputFilenameBuffe
cbHash = MD5LEN;
if (!CryptGetHashParam(hHash, HP_HASHVAL, MD5Hash, &cbHash, 0))
{
- DoOutputErrorString("CryptGetHashParam failed");
+ DoOutputErrorString("CryptGetHashParam failed");
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
-
+
for (i = 0; i < cbHash; i++)
{
PrintHexBytes(OutputFilenameBuffer, MD5Hash, MD5LEN);
}
-
+
return 1;
}
@@ -948,25 +972,25 @@ char* GetHashFromHandle(HANDLE hFile)
char * OutputFilenameBuffer;
if (!MapFile(hFile, &Buffer, &FileSize))
- {
+ {
DoOutputErrorString("MapFile error - check the path is valid and the file has size.");
return 0;
}
-
+
OutputFilenameBuffer = (char*) malloc(MAX_PATH);
if (OutputFilenameBuffer == NULL)
{
DoOutputErrorString("Error allocating memory for hash string");
- return 0;
+ return 0;
}
-
+
if (!GetHash(Buffer, FileSize, (char*)OutputFilenameBuffer))
{
DoOutputErrorString("GetHashFromHandle: GetHash function failed");
- return 0;
+ return 0;
}
-
+
DoOutputDebugString("GetHash returned: %s", OutputFilenameBuffer);
// Check if we have a valid DOS and PE header at the beginning of Buffer
@@ -994,12 +1018,12 @@ char* GetHashFromHandle(HANDLE hFile)
}
}
}
-
+
CloseHandle(hFile);
-
+
// We don't need the file buffer any more
free(Buffer);
-
+
// We leak the OutputFilenameBuffer
return OutputFilenameBuffer;
}
@@ -1011,7 +1035,7 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
LONG e_lfanew;
DWORD NT_Signature;
unsigned int i, j, k;
- BYTE* DecryptedBuffer;
+ BYTE* DecryptedBuffer = NULL;
for (i=0; i<=0xFF; i++)
{
@@ -1023,23 +1047,23 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
e_lfanew = (LONG)*(DWORD*)(Buffer+0x3c);
DoOutputDebugString("Encrypted e_lfanew: 0x%x", e_lfanew);
-
+
for (j=0; j PE_HEADER_LIMIT)
- {
+ {
DoOutputDebugString("The pointer to the PE header seems a tad large: 0x%x", e_lfanew);
//return FALSE;
}
// let's get the NT signature a.k.a PE header
memcpy(&NT_Signature, Buffer+e_lfanew, 4);
-
+
DoOutputDebugString("Encrypted NT_Signature: 0x%x", NT_Signature);
-
+
// let's try decrypting it with the key
for (k=0; k<4; k++)
*((BYTE*)&NT_Signature+k) = *((BYTE*)&NT_Signature+k)^i;
@@ -1050,23 +1074,23 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
if (NT_Signature == IMAGE_NT_SIGNATURE)
{
DoOutputDebugString("Xor-encrypted PE detected, about to dump.\n");
-
+
DecryptedBuffer = (BYTE*)malloc(Size);
-
+
if (DecryptedBuffer == NULL)
{
DoOutputErrorString("Error allocating memory for decrypted PE binary");
return FALSE;
}
-
+
memcpy(DecryptedBuffer, Buffer, Size);
-
+
for (k=0; kAddress = DecryptedBuffer;
DumpImageInCurrentProcess(DecryptedBuffer);
-
+
free(DecryptedBuffer);
return i;
}
@@ -1077,10 +1101,11 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
}
}
}
-
+
// We free can free DecryptedBuffer as it's no longer needed
- free(DecryptedBuffer);
-
+ if(DecryptedBuffer)
+ free(DecryptedBuffer);
+
return FALSE;
}
@@ -1090,32 +1115,32 @@ int ScanPageForNonZero(LPVOID Address)
{
unsigned int p;
DWORD_PTR AddressOfPage;
-
+
if (!Address)
- {
+ {
DoOutputDebugString("ScanPageForNonZero: Error - Supplied address zero.\n");
return 0;
}
-
+
if (!SystemInfo.dwPageSize)
GetSystemInfo(&SystemInfo);
-
+
if (!SystemInfo.dwPageSize)
{
DoOutputErrorString("ScanPageForNonZero: Failed to obtain system page size.\n");
return 0;
}
-
+
AddressOfPage = ((DWORD_PTR)Address/SystemInfo.dwPageSize)*SystemInfo.dwPageSize;
-
- __try
- {
+
+ __try
+ {
for (p=0; pe_lfanew == 0)
+ if ((ULONG)pDosHeader->e_lfanew == 0)
{
// e_lfanew is zero
continue;
@@ -1205,39 +1230,39 @@ int ScanForPE(LPVOID Buffer, SIZE_T Size, LPVOID* Offset)
// e_lfanew points beyond end of region
continue;
}
-
+
pNtHeader = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + (ULONG)pDosHeader->e_lfanew);
-
- if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
+
+ if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
// No 'PE' header
- continue;
+ continue;
}
-
- if ((pNtHeader->FileHeader.Machine == 0) || (pNtHeader->FileHeader.SizeOfOptionalHeader == 0 || pNtHeader->OptionalHeader.SizeOfHeaders == 0))
+
+ if ((pNtHeader->FileHeader.Machine == 0) || (pNtHeader->FileHeader.SizeOfOptionalHeader == 0 || pNtHeader->OptionalHeader.SizeOfHeaders == 0))
{
// Basic requirements
DoOutputDebugString("ScanForPE: Basic requirements failure.\n");
continue;
}
-
+
if (Offset)
{
*Offset = (LPVOID)((char*)Buffer+p);
}
-
+
DoOutputDebugString("ScanForPE: PE image located at: 0x%x\n", (DWORD_PTR)((char*)Buffer+p));
-
+
return 1;
}
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
DoOutputDebugString("ScanForPE: Exception occured reading memory address 0x%x\n", (DWORD_PTR)((char*)Buffer+p));
return 0;
}
}
-
+
DoOutputDebugString("ScanForPE: No PE image located at 0x%x.\n", Buffer);
return 0;
}
@@ -1246,8 +1271,8 @@ int ScanForPE(LPVOID Buffer, SIZE_T Size, LPVOID* Offset)
BOOL TestPERequirements(PIMAGE_NT_HEADERS pNtHeader)
//**************************************************************************************
{
- __try
- {
+ __try
+ {
if ((pNtHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (pNtHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC))
{
//DoOutputDebugString("TestPERequirements: OptionalHeader.Magic bad. (0x%x)", (DWORD_PTR)pNtHeader); // extremely noisy
@@ -1255,49 +1280,49 @@ BOOL TestPERequirements(PIMAGE_NT_HEADERS pNtHeader)
}
//else
// DoOutputDebugString("TestPERequirements: OptionalHeader.Magic ok!: 0x%x (0x%x)", pNtHeader->OptionalHeader.Magic, (DWORD_PTR)pNtHeader);
-
+
// Basic requirements
- if
+ if
(
- pNtHeader->FileHeader.Machine == 0 ||
- pNtHeader->FileHeader.SizeOfOptionalHeader == 0 ||
+ pNtHeader->FileHeader.Machine == 0 ||
+ pNtHeader->FileHeader.SizeOfOptionalHeader == 0 ||
pNtHeader->OptionalHeader.SizeOfHeaders == 0 //||
//pNtHeader->OptionalHeader.FileAlignment == 0
- )
+ )
{
- //DoOutputDebugString("TestPERequirements: Basic requirements failure (0x%x).\n", (DWORD_PTR)pNtHeader); // very noisy
+ //DoOutputDebugString("TestPERequirements: Basic requirements failure (0x%x).\n", (DWORD_PTR)pNtHeader); // very noisy
return FALSE;
}
- if (!(pNtHeader->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
+ if (!(pNtHeader->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
{
DoOutputDebugString("TestPERequirements: Characteristics bad. (0x%x)", (DWORD_PTR)pNtHeader);
return FALSE;
}
- if (pNtHeader->FileHeader.SizeOfOptionalHeader & (sizeof (ULONG_PTR) - 1))
+ if (pNtHeader->FileHeader.SizeOfOptionalHeader & (sizeof (ULONG_PTR) - 1))
{
DoOutputDebugString("TestPERequirements: SizeOfOptionalHeader bad. (0x%x)", (DWORD_PTR)pNtHeader);
return FALSE;
}
-
- if (((pNtHeader->OptionalHeader.FileAlignment-1) & pNtHeader->OptionalHeader.FileAlignment) != 0)
+
+ if (((pNtHeader->OptionalHeader.FileAlignment-1) & pNtHeader->OptionalHeader.FileAlignment) != 0)
{
DoOutputDebugString("TestPERequirements: FileAlignment invalid. (0x%x)", (DWORD_PTR)pNtHeader);
return FALSE;
}
-
- if (pNtHeader->OptionalHeader.SectionAlignment < pNtHeader->OptionalHeader.FileAlignment)
- {
+
+ if (pNtHeader->OptionalHeader.SectionAlignment < pNtHeader->OptionalHeader.FileAlignment)
+ {
DoOutputDebugString("TestPERequirements: FileAlignment greater than SectionAlignment.\n (0x%x)", (DWORD_PTR)pNtHeader);
- return FALSE;
- }
+ return FALSE;
+ }
// To pass the above tests it should now be safe to assume it's a PE image
return TRUE;
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
DoOutputDebugString("TestPERequirements: Exception occured reading region at 0x%x\n", (DWORD_PTR)(pNtHeader));
return FALSE;
}
@@ -1310,14 +1335,14 @@ int IsDisguisedPEHeader(LPVOID Buffer)
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeader = NULL;
WORD* MachineProbe;
-
- __try
- {
+
+ __try
+ {
pDosHeader = (PIMAGE_DOS_HEADER)Buffer;
if (pDosHeader->e_lfanew && (ULONG)pDosHeader->e_lfanew < PE_HEADER_LIMIT && ((ULONG)pDosHeader->e_lfanew & 3) == 0)
pNtHeader = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + (ULONG)pDosHeader->e_lfanew);
-
+
if (!pDosHeader->e_lfanew)
{
// In case the header until and including 'PE' has been zeroed
@@ -1330,7 +1355,7 @@ int IsDisguisedPEHeader(LPVOID Buffer)
break;
}
MachineProbe += sizeof(WORD);
- }
+ }
}
if (pNtHeader && TestPERequirements(pNtHeader))
@@ -1350,17 +1375,17 @@ int IsDisguisedPEHeader(LPVOID Buffer)
}
}
MachineProbe += sizeof(WORD);
- }
+ }
if (pNtHeader && TestPERequirements(pNtHeader))
- return 1;
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- DoOutputDebugString("IsDisguisedPEHeader: Exception occured reading region at 0x%x\n", (DWORD_PTR)(Buffer));
- return -1;
+ return 1;
}
-
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //DoOutputDebugString("IsDisguisedPEHeader: Exception occured reading region at 0x%x\n", (DWORD_PTR)(Buffer));
+ return 0;
+ }
+
//DoOutputDebugString("IsDisguisedPEHeader: No PE image located\n (0x%x)", (DWORD_PTR)Buffer);
return 0;
}
@@ -1371,17 +1396,17 @@ int ScanForDisguisedPE(LPVOID Buffer, SIZE_T Size, LPVOID* Offset)
{
SIZE_T p;
int RetVal;
-
+
if (Size == 0)
{
DoOutputDebugString("ScanForDisguisedPE: Error, zero size given\n");
return 0;
}
-
+
for (p=0; p < Size - PE_HEADER_LIMIT; p++) // we want to stop short of the max look-ahead in IsDisguisedPEHeader
{
RetVal = IsDisguisedPEHeader((BYTE*)Buffer+p);
-
+
if (!RetVal)
continue;
else if (RetVal == -1)
@@ -1389,17 +1414,17 @@ int ScanForDisguisedPE(LPVOID Buffer, SIZE_T Size, LPVOID* Offset)
DoOutputDebugString("ScanForDisguisedPE: Exception occured scanning buffer at 0x%x\n", (DWORD_PTR)((BYTE*)Buffer+p));
return 0;
}
-
+
if (Offset)
{
*Offset = (LPVOID)((BYTE*)Buffer+p);
}
-
+
DoOutputDebugString("ScanForDisguisedPE: PE image located at: 0x%x\n", (DWORD_PTR)((BYTE*)Buffer+p));
-
+
return 1;
}
-
+
DoOutputDebugString("ScanForDisguisedPE: No PE image located in range 0x%x-0x%x.\n", Buffer, (DWORD_PTR)Buffer + Size);
return 0;
}
@@ -1411,20 +1436,20 @@ BOOL DumpPEsInRange(LPVOID Buffer, SIZE_T Size)
PBYTE PEImage;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeader = NULL;
-
+
BOOL RetVal = FALSE;
LPVOID PEPointer = Buffer;
-
+
DoOutputDebugString("DumpPEsInRange: Scanning range 0x%x - 0x%x.\n", Buffer, (BYTE*)Buffer + Size);
while (ScanForDisguisedPE(PEPointer, Size - ((DWORD_PTR)PEPointer - (DWORD_PTR)Buffer), &PEPointer))
{
pDosHeader = (PIMAGE_DOS_HEADER)PEPointer;
-
+
if (*(WORD*)PEPointer != IMAGE_DOS_SIGNATURE || (*(DWORD*)((BYTE*)pDosHeader + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE))
- {
+ {
DoOutputDebugString("DumpPEsInRange: Disguised PE image (bad MZ and/or PE headers) at 0x%x.\n", PEPointer);
-
+
// We want to fix the PE header in the dump (for e.g. disassembly etc)
PEImage = (BYTE*)calloc(Size - ((DWORD_PTR)PEPointer - (DWORD_PTR)Buffer), sizeof(PUCHAR));
memcpy(PEImage, PEPointer, Size - ((DWORD_PTR)PEPointer - (DWORD_PTR)Buffer));
@@ -1443,7 +1468,7 @@ BOOL DumpPEsInRange(LPVOID Buffer, SIZE_T Size)
}
MachineProbe += sizeof(WORD);
}
-
+
if (pNtHeader)
pDosHeader->e_lfanew = (LONG)((PUCHAR)pNtHeader - (PUCHAR)pDosHeader);
}
@@ -1464,7 +1489,7 @@ BOOL DumpPEsInRange(LPVOID Buffer, SIZE_T Size)
}
}
MachineProbe += sizeof(WORD);
-
+
if (pNtHeader && (PUCHAR)pNtHeader == (PUCHAR)pDosHeader && pNtHeader->OptionalHeader.SizeOfHeaders)
{
SIZE_T HeaderShift = sizeof(IMAGE_DOS_HEADER);
@@ -1475,14 +1500,14 @@ BOOL DumpPEsInRange(LPVOID Buffer, SIZE_T Size)
pDosHeader->e_lfanew = (LONG)((PUCHAR)pNtHeader - (PUCHAR)pDosHeader);
DoOutputDebugString("DumpPEsInRange: pNtHeader moved from 0x%x to 0x%x, e_lfanew 0x%x\n", pDosHeader, pNtHeader, pDosHeader->e_lfanew);
}
- }
+ }
}
-
+
*(WORD*)pDosHeader = IMAGE_DOS_SIGNATURE;
*(DWORD*)((PUCHAR)pDosHeader + pDosHeader->e_lfanew) = IMAGE_NT_SIGNATURE;
SetCapeMetaData(INJECTION_PE, 0, NULL, (PVOID)pDosHeader);
-
+
if (DumpImageInCurrentProcess((LPVOID)pDosHeader))
{
DoOutputDebugString("DumpPEsInRange: Dumped PE image from 0x%x.\n", pDosHeader);
@@ -1492,12 +1517,12 @@ BOOL DumpPEsInRange(LPVOID Buffer, SIZE_T Size)
DoOutputDebugString("DumpPEsInRange: Failed to dump PE image from 0x%x.\n", pDosHeader);
if (PEImage)
- free(PEImage);
+ free(PEImage);
}
else
{
SetCapeMetaData(INJECTION_PE, 0, NULL, (PVOID)PEPointer);
-
+
if (DumpImageInCurrentProcess((LPVOID)PEPointer))
{
DoOutputDebugString("DumpPEsInRange: Dumped PE image from 0x%x.\n", PEPointer);
@@ -1506,10 +1531,10 @@ BOOL DumpPEsInRange(LPVOID Buffer, SIZE_T Size)
else
DoOutputDebugString("DumpPEsInRange: Failed to dump PE image from 0x%x.\n", PEPointer);
}
-
+
(BYTE*)PEPointer += PE_HEADER_LIMIT;
}
-
+
return RetVal;
}
@@ -1525,7 +1550,7 @@ int DumpMemory(LPVOID Buffer, SIZE_T Size)
FullPathName = GetName();
hOutputFile = CreateFile(FullPathName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
-
+
if (hOutputFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS)
{
DoOutputDebugString("DumpMemory: CAPE output filename exists already: %s", FullPathName);
@@ -1537,35 +1562,35 @@ int DumpMemory(LPVOID Buffer, SIZE_T Size)
{
DoOutputErrorString("DumpMemory: Could not create CAPE output file");
free(FullPathName);
- return 0;
- }
-
+ return 0;
+ }
+
dwBytesWritten = 0;
-
+
DoOutputDebugString("DumpMemory: CAPE output file successfully created: %s", FullPathName);
BufferCopy = (LPVOID)((BYTE*)malloc(Size));
-
+
if (BufferCopy == NULL)
{
DoOutputDebugString("DumpMemory: Failed to allocate memory for buffer copy.\n");
return FALSE;
}
-
- __try
- {
+
+ __try
+ {
memcpy(BufferCopy, Buffer, Size);
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
DoOutputDebugString("DumpMemory: Exception occured reading memory address 0x%x\n", Buffer);
return 0;
}
-
+
if (FALSE == WriteFile(hOutputFile, BufferCopy, (DWORD)Size, &dwBytesWritten, NULL))
{
DoOutputErrorString("DumpMemory: WriteFile error on CAPE output file");
- free(FullPathName);
+ free(FullPathName);
free(BufferCopy);
return 0;
}
@@ -1574,13 +1599,13 @@ int DumpMemory(LPVOID Buffer, SIZE_T Size)
CapeMetaData->Address = Buffer;
CapeMetaData->Size = Size;
-
+
CapeOutputFile(FullPathName);
-
+
// We can free the filename buffers
- free(FullPathName);
+ free(FullPathName);
free(BufferCopy);
-
+
return 1;
}
@@ -1591,10 +1616,10 @@ BOOL DumpRegion(PVOID Address)
MEMORY_BASIC_INFORMATION MemInfo;
PVOID OriginalAllocationBase, OriginalBaseAddress, AddressOfPage;
SIZE_T AllocationSize, OriginalRegionSize;
-
+
if (!SystemInfo.dwPageSize)
GetSystemInfo(&SystemInfo);
-
+
if (!SystemInfo.dwPageSize)
{
DoOutputErrorString("DumpRegion: Failed to obtain system page size.\n");
@@ -1606,12 +1631,12 @@ BOOL DumpRegion(PVOID Address)
DoOutputErrorString("DumpRegion: unable to query memory address 0x%x", Address);
return 0;
}
-
+
OriginalAllocationBase = MemInfo.AllocationBase;
OriginalBaseAddress = MemInfo.BaseAddress;
OriginalRegionSize = MemInfo.RegionSize;
AddressOfPage = OriginalAllocationBase;
-
+
while (MemInfo.AllocationBase == OriginalAllocationBase)
{
(PUCHAR)AddressOfPage += SystemInfo.dwPageSize;
@@ -1620,9 +1645,9 @@ BOOL DumpRegion(PVOID Address)
{
DoOutputErrorString("DumpRegion: unable to query memory page 0x%x", AddressOfPage);
return 0;
- }
+ }
}
-
+
AllocationSize = (SIZE_T)((DWORD_PTR)AddressOfPage - (DWORD_PTR)OriginalAllocationBase);
SetCapeMetaData(EXTRACTION_SHELLCODE, 0, NULL, (PVOID)OriginalAllocationBase);
@@ -1638,9 +1663,9 @@ BOOL DumpRegion(PVOID Address)
else
{
DoOutputDebugString("DumpRegion: Failed to dump entire allocation from 0x%p size 0x%x.\n", OriginalAllocationBase, AllocationSize);
-
+
SetCapeMetaData(EXTRACTION_SHELLCODE, 0, NULL, (PVOID)OriginalBaseAddress);
-
+
if (DumpMemory(OriginalBaseAddress, OriginalRegionSize))
{
if (address_is_in_stack(Address))
@@ -1697,119 +1722,150 @@ int DumpCurrentProcess()
}
//**************************************************************************************
-int DumpModuleInCurrentProcess(LPVOID ModuleBase)
+int DumpImageInCurrentProcess(LPVOID ImageBase)
//**************************************************************************************
{
PIMAGE_DOS_HEADER pDosHeader;
+ PIMAGE_NT_HEADERS pNtHeader;
+
+ pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
+
+ if (DumpCount >= DUMP_MAX)
+ {
+ DoOutputDebugString("DumpImageInCurrentProcess: CAPE dump limit reached.\n");
+ return 0;
+ }
+
+ if (*(WORD*)ImageBase != IMAGE_DOS_SIGNATURE)
+ {
+ DoOutputDebugString("DumpImageInCurrentProcess: No DOS signature in header.\n");
+ return 0;
+ }
- if (!IsDisguisedPEHeader(ModuleBase))
+ if (!pDosHeader->e_lfanew || pDosHeader->e_lfanew > PE_HEADER_LIMIT)
{
- DoOutputDebugString("DumpModuleInCurrentProcess: Not a valid image at 0x%p - cannot dump.\n", ModuleBase);
+ DoOutputDebugString("DumpImageInCurrentProcess: bad e_lfanew.\n");
return 0;
}
-
- pDosHeader = (PIMAGE_DOS_HEADER)ModuleBase;
-
- if (*(WORD*)ModuleBase != IMAGE_DOS_SIGNATURE || (*(DWORD*)((BYTE*)pDosHeader + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE))
- {
- PBYTE PEImage;
- SIZE_T ImageSize;
-
- DoOutputDebugString("DumpModuleInCurrentProcess: Disguised PE image (bad MZ and/or PE headers) at 0x%p.\n", ModuleBase);
-
- // We want to fix the PE header in the dump (for e.g. disassembly etc)
- ImageSize = GetPESize(ModuleBase);
- PEImage = (BYTE*)malloc(ImageSize);
- memcpy(PEImage, ModuleBase, ImageSize);
- pDosHeader = (PIMAGE_DOS_HEADER)PEImage;
-
- *(WORD*)PEImage = IMAGE_DOS_SIGNATURE;
- *(DWORD*)(PEImage + pDosHeader->e_lfanew) = IMAGE_NT_SIGNATURE;
-
- ModuleBase = PEImage;
- }
-
- SetCapeMetaData(EXTRACTION_PE, 0, NULL, (PVOID)ModuleBase);
-
- if (DumpCount < DUMP_MAX && ScyllaDumpProcess(GetCurrentProcess(), (DWORD_PTR)ModuleBase, 0))
+
+ pNtHeader = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + (ULONG)pDosHeader->e_lfanew);
+
+ if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
- DumpCount++;
- return 1;
+ // No 'PE' header
+ DoOutputDebugString("DumpImageInCurrentProcess: Invalid PE signature in header.\n");
+ return 0;
}
- return 0;
+ if ((pNtHeader->FileHeader.Machine == 0) || (pNtHeader->FileHeader.SizeOfOptionalHeader == 0 || pNtHeader->OptionalHeader.SizeOfHeaders == 0))
+ {
+ // Basic requirements
+ DoOutputDebugString("DumpImageInCurrentProcess: PE image invalid.\n");
+ return 0;
+ }
+
+ if (IsPeImageVirtual(ImageBase) == FALSE)
+ {
+ DoOutputDebugString("DumpImageInCurrentProcess: Attempting to dump 'raw' PE image.\n");
+
+ if (ScyllaDumpPE((DWORD_PTR)ImageBase))
+ {
+ DumpCount++;
+ return 1;
+ }
+ else
+ {
+ // failed to dump pe image
+ DoOutputDebugString("DumpImageInCurrentProcess: Failed to dump 'raw' PE image.\n");
+ return 0;
+ }
+ }
+
+ DoOutputDebugString("DumpImageInCurrentProcess: Attempting to dump virtual PE image.\n");
+
+ if (!ScyllaDumpProcess(GetCurrentProcess(), (DWORD_PTR)ImageBase, 0))
+ {
+ DoOutputDebugString("DumpImageInCurrentProcess: Failed to dump PE as virtual image.\n");
+ return 0;
+ }
+
+ DumpCount++;
+ return 1;
}
//**************************************************************************************
-int DumpImageInCurrentProcess(LPVOID ImageBase)
+unsigned int DumpImageToFileHandle(LPVOID ImageBase, HANDLE FileHandle)
//**************************************************************************************
{
+ unsigned int BytesWritten;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeader;
-
+
pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
if (DumpCount >= DUMP_MAX)
{
- DoOutputDebugString("DumpImageInCurrentProcess: CAPE dump limit reached.\n");
+ DoOutputDebugString("DumpImageToFileHandle: CAPE dump limit reached.\n");
return 0;
}
if (*(WORD*)ImageBase != IMAGE_DOS_SIGNATURE)
{
- DoOutputDebugString("DumpImageInCurrentProcess: No DOS signature in header.\n");
+ DoOutputDebugString("DumpImageToFileHandle: No DOS signature in header.\n");
return 0;
}
-
+
if (!pDosHeader->e_lfanew || pDosHeader->e_lfanew > PE_HEADER_LIMIT)
{
- DoOutputDebugString("DumpImageInCurrentProcess: bad e_lfanew.\n");
- return 0;
+ DoOutputDebugString("DumpImageToFileHandle: bad e_lfanew.\n");
+ return 0;
}
-
+
pNtHeader = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + (ULONG)pDosHeader->e_lfanew);
-
- if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
+
+ if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
// No 'PE' header
- DoOutputDebugString("DumpImageInCurrentProcess: Invalid PE signature in header.\n");
+ DoOutputDebugString("DumpImageToFileHandle: Invalid PE signature in header.\n");
return 0;
}
-
- if ((pNtHeader->FileHeader.Machine == 0) || (pNtHeader->FileHeader.SizeOfOptionalHeader == 0 || pNtHeader->OptionalHeader.SizeOfHeaders == 0))
+
+ if ((pNtHeader->FileHeader.Machine == 0) || (pNtHeader->FileHeader.SizeOfOptionalHeader == 0 || pNtHeader->OptionalHeader.SizeOfHeaders == 0))
{
// Basic requirements
- DoOutputDebugString("DumpImageInCurrentProcess: PE image invalid.\n");
+ DoOutputDebugString("DumpImageToFileHandle: PE image invalid.\n");
return 0;
}
-
+
if (IsPeImageVirtual(ImageBase) == FALSE)
{
- DoOutputDebugString("DumpImageInCurrentProcess: Attempting to dump 'raw' PE image.\n");
-
- if (ScyllaDumpPE((DWORD_PTR)ImageBase))
+ DoOutputDebugString("DumpImageToFileHandle: Attempting to dump 'raw' PE image.\n");
+
+ if (ScyllaDumpPEToFileHandle((DWORD_PTR)ImageBase, FileHandle))
{
DumpCount++;
- return 1;
+ return 1;
}
else
{
// failed to dump pe image
- DoOutputDebugString("DumpImageInCurrentProcess: Failed to dump 'raw' PE image.\n");
- return 0;
+ DoOutputDebugString("DumpImageToFileHandle: Failed to dump 'raw' PE image.\n");
+ return 0;
}
}
- DoOutputDebugString("DumpImageInCurrentProcess: Attempting to dump virtual PE image.\n");
-
- if (!ScyllaDumpProcess(GetCurrentProcess(), (DWORD_PTR)ImageBase, 0))
+ DoOutputDebugString("DumpImageToFileHandle: Attempting to dump virtual PE image.\n");
+
+ BytesWritten = ScyllaDumpProcessToFileHandle(GetCurrentProcess(), (DWORD_PTR)ImageBase, 0, FileHandle);
+
+ if (!BytesWritten)
{
- DoOutputDebugString("DumpImageInCurrentProcess: Failed to dump PE as virtual image.\n");
- return 0;
+ DoOutputDebugString("DumpImageToFileHandle: Failed to dump PE as virtual image.\n");
+ return 0;
}
DumpCount++;
- return 1;
+ return 1;
}
//**************************************************************************************
@@ -1830,7 +1886,7 @@ int DumpPE(LPVOID Buffer)
//**************************************************************************************
{
SetCapeMetaData(INJECTION_PE, 0, NULL, (PVOID)Buffer);
-
+
if (DumpCount < DUMP_MAX && ScyllaDumpPE((DWORD_PTR)Buffer))
{
DumpCount++;
@@ -1841,52 +1897,294 @@ int DumpPE(LPVOID Buffer)
}
//**************************************************************************************
-int RoutineProcessDump()
+void DumpInterestingRegions(MEMORY_BASIC_INFORMATION MemInfo, PVOID CallerBase)
//**************************************************************************************
{
- if (g_config.procdump && ProcessDumped == FALSE)
+ //PIMAGE_DOS_HEADER pDosHeader;
+ //wchar_t *MappedPath, *ModulePath, *AbsoluteMapped, *AbsoluteModule;
+
+ if (!MemInfo.BaseAddress)
+ return;
+
+ if (MemInfo.BaseAddress == (PVOID)g_our_dll_base)
+ return;
+
+ __try
{
- ProcessDumped = TRUE; // this prevents a second call before the first is complete
+ BYTE Test = *(BYTE*)MemInfo.BaseAddress;
+ Test = *(BYTE*)MemInfo.BaseAddress + PE_HEADER_LIMIT;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ // No point in continuing if we can't read!
+ return;
+ }
+
+ if (MemInfo.BaseAddress == ImageBase)
+ {
+ DoOutputDebugString("DumpInterestingRegions: Dumping Imagebase at 0x%p.\n", ImageBase);
if (g_config.import_reconstruction)
- {
- if (base_of_dll_of_interest)
- ProcessDumped = ScyllaDumpProcessFixImports(GetCurrentProcess(), base_of_dll_of_interest, 0);
- else
- ProcessDumped = ScyllaDumpCurrentProcessFixImports(0);
- }
+ ProcessDumped = ScyllaDumpProcessFixImports(GetCurrentProcess(), (DWORD_PTR)ImageBase, 0);
else
+ ProcessDumped = ScyllaDumpProcess(GetCurrentProcess(), (DWORD_PTR)ImageBase, 0);
+ }
+ // Disable dumping of all calling regions for the moment as this needs further testing.
+ // (This causes lots of useless dumps from Word processes, for example.)
+ //else if (lookup_get(&g_caller_regions, (ULONG_PTR)MemInfo.BaseAddress, NULL) || MemInfo.BaseAddress == CallerBase)
+ else if (MemInfo.BaseAddress == CallerBase)
+ {
+ DoOutputDebugString("DumpInterestingRegions: Dumping calling region at 0x%p.\n", MemInfo.BaseAddress);
+
+ CapeMetaData->ModulePath = NULL;
+
+ if (IsDisguisedPEHeader(MemInfo.BaseAddress))
{
- if (base_of_dll_of_interest)
- ProcessDumped = ScyllaDumpProcess(GetCurrentProcess(), base_of_dll_of_interest, 0);
- else
- ProcessDumped = ScyllaDumpCurrentProcess(0);
+ CapeMetaData->Address = MemInfo.BaseAddress;
+ CapeMetaData->DumpType = EXTRACTION_PE;
+ ScyllaDumpProcess(GetCurrentProcess(), (DWORD_PTR)MemInfo.BaseAddress, 0);
}
+ else
+ DumpRegion(MemInfo.BaseAddress);
}
+}
+
+//**************************************************************************************
+int DoProcessDump(PVOID CallerBase)
+//**************************************************************************************
+{
+ HANDLE hSnapShot;
+ THREADENTRY32 ThreadInfo;
+ PUCHAR Address;
+ MEMORY_BASIC_INFORMATION MemInfo;
+ HANDLE FileHandle;
+ char *FullDumpPath, *OutputFilename;
+
+ EnterCriticalSection(&ProcessDumpCriticalSection);
+
+ if (base_of_dll_of_interest)
+ ImageBase = (PVOID)base_of_dll_of_interest;
+ else
+ ImageBase = GetModuleHandle(NULL);
+
+ PHANDLE SuspendedThreads = (PHANDLE)malloc(SUSPENDED_THREAD_MAX*sizeof(HANDLE));
+ DWORD ThreadId = GetCurrentThreadId(), SuspendedThreadCount = 0;
+
+ if (!SystemInfo.dwPageSize)
+ GetSystemInfo(&SystemInfo);
+
+ if (!SystemInfo.dwPageSize)
+ {
+ DoOutputErrorString("DoProcessDump: Failed to obtain system page size.\n");
+ goto out;
+ }
+
+ // suspend other threads before dump
+ hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ Thread32First(hSnapShot, &ThreadInfo);
+
+ do
+ {
+ if (ThreadInfo.th32OwnerProcessID != CapeMetaData->Pid || ThreadInfo.th32ThreadID == ThreadId || SuspendedThreadCount >= SUSPENDED_THREAD_MAX)
+ continue;
- return ProcessDumped;
+ SuspendedThreads[SuspendedThreadCount] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, ThreadInfo.th32ThreadID);
+
+ if (SuspendedThreads[SuspendedThreadCount])
+ {
+ SuspendThread(SuspendedThreads[SuspendedThreadCount]);
+ SuspendedThreadCount++;
+ }
+ }
+ while(Thread32Next(hSnapShot, &ThreadInfo));
+
+ if (g_config.procmemdump)
+ {
+ FullDumpPath = GetResultsPath("memory");
+
+ if (!FullDumpPath)
+ {
+ DoOutputDebugString("DoProcessDump: Unable to get path to dump file directory.\n");
+ goto out;
+ }
+
+ OutputFilename = (char*)malloc(MAX_PATH);
+
+ sprintf_s(OutputFilename, MAX_PATH, "%d.dmp", CapeMetaData->Pid);
+
+ PathAppend(FullDumpPath, OutputFilename);
+
+ FileHandle = CreateFile(FullDumpPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (FileHandle == INVALID_HANDLE_VALUE)
+ {
+ DoOutputDebugString("DoProcessDump: Unable to create dump file for full process memory dump.\n");
+ goto out;
+ }
+
+ DoOutputDebugString("DoProcessDump: Created dump file for full process memory dump: %s.\n", FullDumpPath);
+ }
+
+ for (Address = (PUCHAR)SystemInfo.lpMinimumApplicationAddress; Address < (PUCHAR)SystemInfo.lpMaximumApplicationAddress;)
+ {
+ if (!VirtualQuery(Address, &MemInfo, sizeof(MemInfo)))
+ {
+ Address += SystemInfo.dwPageSize;
+ continue;
+ }
+
+ if (!(MemInfo.State & MEM_COMMIT) || !(MemInfo.Type & (MEM_IMAGE | MEM_MAPPED | MEM_PRIVATE)))
+ {
+ Address += MemInfo.RegionSize;
+ continue;
+ }
+
+ if (g_config.procdump)
+ {
+ DumpInterestingRegions(MemInfo, CallerBase);
+ }
+
+ if (g_config.procmemdump)
+ {
+ LARGE_INTEGER BufferAddress;
+ DWORD BytesWritten;
+ PVOID TempBuffer;
+
+ BufferAddress.QuadPart = (ULONGLONG)Address;
+ TempBuffer = malloc(MemInfo.RegionSize);
+ if (!TempBuffer)
+ {
+ DoOutputDebugString("DoProcessDump: Error allocating memory for copy of region at 0x%p, size 0x%x.\n", MemInfo.BaseAddress, MemInfo.RegionSize);
+ goto out;
+ }
+ __try
+ {
+ memcpy(TempBuffer, MemInfo.BaseAddress, MemInfo.RegionSize);
+ WriteFile(FileHandle, &BufferAddress, sizeof(BufferAddress), &BytesWritten, NULL);
+ WriteFile(FileHandle, &(DWORD)MemInfo.RegionSize, sizeof(DWORD), &BytesWritten, NULL);
+ WriteFile(FileHandle, &MemInfo.State, sizeof(MemInfo.State), &BytesWritten, NULL);
+ WriteFile(FileHandle, &MemInfo.Type, sizeof(MemInfo.Type), &BytesWritten, NULL);
+ WriteFile(FileHandle, &MemInfo.Protect, sizeof(MemInfo.Protect), &BytesWritten, NULL);
+ WriteFile(FileHandle, TempBuffer, (DWORD)MemInfo.RegionSize, &BytesWritten, NULL);
+ free(TempBuffer);
+ if (BytesWritten != MemInfo.RegionSize)
+ DoOutputDebugString("DoProcessDump: Anomaly detected, wrote only 0x%x of 0x%x bytes to memory dump from region 0x%p.\n", BytesWritten, MemInfo.RegionSize, MemInfo.BaseAddress);
+ //else
+ // DoOutputDebugString("DoProcessDump: Added 0x%x byte region at 0x%p to memory dump (protect 0x%x).\n", MemInfo.RegionSize, MemInfo.BaseAddress, MemInfo.Protect);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ free(TempBuffer);
+ //DoOutputDebugString("DoProcessDump: Exception attempting to dump region at 0x%p, size 0x%x.\n", MemInfo.BaseAddress, MemInfo.RegionSize);
+ }
+ }
+
+ Address += MemInfo.RegionSize;
+ }
+
+out:
+ if (g_config.procmemdump)
+ {
+ if (FileHandle)
+ {
+ DoOutputDebugString("DoProcessDump: Full process memory dump saved to file: %s.\n", FullDumpPath);
+ CloseHandle(FileHandle);
+ }
+ if (OutputFilename)
+ free(OutputFilename);
+ if (FullDumpPath)
+ free(FullDumpPath);
+ }
+
+ if (SuspendedThreads)
+ {
+ for (unsigned int i = 0; i < SuspendedThreadCount; i++)
+ {
+ ResumeThread(SuspendedThreads[i]);
+ CloseHandle(SuspendedThreads[i]);
+ }
+ free(SuspendedThreads);
+ }
+
+ LeaveCriticalSection(&ProcessDumpCriticalSection);
+ return ProcessDumped;
+}
+
+void RestoreHeaders()
+{
+ DWORD ImportsRVA, ImportsSize, SizeOfHeaders, dwProtect;
+ PVOID BaseAddress, ImportsVA;
+ PIMAGE_DOS_HEADER pDosHeader;
+ PIMAGE_NT_HEADERS pNtHeaders;
+
+ BaseAddress = GetModuleHandle(NULL);
+ SizeOfHeaders = sizeof(IMAGE_NT_HEADERS);
+ pDosHeader = (PIMAGE_DOS_HEADER)BaseAddress;
+ pNtHeaders = (PIMAGE_NT_HEADERS)((PBYTE)BaseAddress + pDosHeader->e_lfanew);
+ ImportsRVA = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
+ ImportsSize = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
+ ImportsVA = (PBYTE)BaseAddress + ImportsRVA;
+
+ // Check if we have a PE header after import table
+ if (*(DWORD*)((PBYTE)ImportsVA + ImportsSize) != IMAGE_NT_SIGNATURE)
+ return;
+
+ // Set page permissions to allow writing of original headers
+ if (!VirtualProtect((PBYTE)BaseAddress, SizeOfHeaders, PAGE_EXECUTE_READWRITE, &dwProtect))
+ {
+ DoOutputErrorString("RestoreHeaders: Failed to modify memory page protection of NtHeaders");
+ return;
+ }
+
+ memcpy((PBYTE)BaseAddress + pDosHeader->e_lfanew, (PBYTE)ImportsVA + ImportsSize, SizeOfHeaders);
+
+ // Restore original protection
+ if (!VirtualProtect((PBYTE)BaseAddress, SizeOfHeaders, dwProtect, &dwProtect))
+ {
+ DoOutputErrorString("RestoreHeaders: Failed to restore previous memory page protection");
+ return;
+ }
+
+ // Free memory
+ if (!VirtualFree(ImportsVA, 0, MEM_RELEASE))
+ {
+ DoOutputErrorString("RestoreHeaders: Failed to free memory for patched IAT");
+ return;
+ }
+
+ DoOutputDebugString("RestoreHeaders: Restored original import table.\n");
}
void init_CAPE()
{
+ char* CommandLine;
+
+ // Restore headers in case of IAT patching
+ RestoreHeaders();
+
// Initialise CAPE global variables
//
#ifndef STANDALONE
CapeMetaData = (PCAPEMETADATA)malloc(sizeof(CAPEMETADATA));
CapeMetaData->Pid = GetCurrentProcessId();
CapeMetaData->ProcessPath = (char*)malloc(MAX_PATH);
- WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, (LPCWSTR)our_process_path, (int)wcslen(our_process_path)+1, CapeMetaData->ProcessPath, MAX_PATH, NULL, NULL);
+ WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, (LPCWSTR)our_process_path_w, (int)wcslen(our_process_path_w)+1, CapeMetaData->ProcessPath, MAX_PATH, NULL, NULL);
+ CommandLine = (char*)malloc(MAX_PATH);
+ WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, (LPCWSTR)our_commandline, (int)wcslen(our_commandline)+1, CommandLine, MAX_PATH, NULL, NULL);
+
// This is package (and technique) dependent:
- CapeMetaData->DumpType = PROCDUMP;
+ CapeMetaData->DumpType = EXTRACTION_SHELLCODE;
ProcessDumped = FALSE;
-
+
DumpCount = 0;
// This flag controls whether a dump is automatically
// made at the end of a process' lifetime.
// It is normally only set in the base packages,
// or upon submission. (This overrides submission.)
- // g_config.procmemdump = 0;
+ g_config.procdump = 0;
+
+ InitializeCriticalSection(&ProcessDumpCriticalSection);
// Cuckoo debug output level for development (0=none, 2=max)
// g_config.debug = 2;
@@ -1900,10 +2198,16 @@ void init_CAPE()
DoOutputDebugString("Failed to initialise debugger.\n");
#ifdef _WIN64
- DoOutputDebugString("CAPE initialised: 64-bit base package loaded at 0x%p, process image base 0x%p\n", g_our_dll_base, GetModuleHandle(NULL));
+ DoOutputDebugString("CAPE initialised: 64-bit QakBot package loaded in process %d at 0x%p, image base 0x%p, stack from 0x%p-0x%p\n", GetCurrentProcessId(), g_our_dll_base, GetModuleHandle(NULL), get_stack_bottom(), get_stack_top());
#else
- DoOutputDebugString("CAPE initialised: 32-bit base package loaded at 0x%p, process image base 0x%p\n", g_our_dll_base, GetModuleHandle(NULL));
+ DoOutputDebugString("CAPE initialised: 32-bit QakBot package loaded in process %d at 0x%x, image base 0x%x, stack from 0x%x-0x%x\n", GetCurrentProcessId(), g_our_dll_base, GetModuleHandle(NULL), get_stack_bottom(), get_stack_top());
#endif
-
+ DoOutputDebugString("Commandline: %s.\n", CommandLine);
+
+#ifdef CAPE_TRACE
+ if (!g_config.base_on_apiname[0])
+ SetInitialBreakpoints(GetModuleHandle(NULL));
+#endif
+
return;
}
diff --git a/CAPE/CAPE.h b/CAPE/CAPE.h
index e24309b..520c473 100644
--- a/CAPE/CAPE.h
+++ b/CAPE/CAPE.h
@@ -20,12 +20,14 @@ extern WCHAR s_wzDllPath[MAX_PATH];
extern CHAR s_szDllPath[MAX_PATH];
//Global debugger switch
-#define DEBUGGER_ENABLED 0
+#define DEBUGGER_ENABLED 1
-void GetHookCallerBase();
+PVOID GetHookCallerBase();
PVOID GetPageAddress(PVOID Address);
PVOID GetAllocationBase(PVOID Address);
+BOOL InsideMonitor(LPVOID* ReturnAddress, LPVOID Address);
BOOL TranslatePathFromDeviceToLetter(__in TCHAR *DeviceFilePath, __out TCHAR* DriveLetterFilePath, __inout LPDWORD lpdwBufferSize);
+void PrintHexBytes(__in char* TextBuffer, __in BYTE* HexBuffer, __in unsigned int Count);
BOOL DumpPEsInRange(LPVOID Buffer, SIZE_T Size);
BOOL DumpRegion(PVOID Address);
int DumpMemory(LPVOID Buffer, SIZE_T Size);
@@ -112,7 +114,7 @@ struct InjectionSectionView *SectionViewList;
#define PLUGX_SIGNATURE 0x5658 // 'XV'
-typedef struct CapeMetadata
+typedef struct CapeMetadata
{
char* ProcessPath;
char* ModulePath;
@@ -130,29 +132,34 @@ BOOL SetCapeMetaData(DWORD DumpType, DWORD TargetPid, HANDLE hTargetProcess, PVO
enum {
PROCDUMP = 0,
-
+
COMPRESSION = 1,
-
+
INJECTION_PE = 3,
INJECTION_SHELLCODE = 4,
//INJECTION_RUNPE = 5,
EXTRACTION_PE = 8,
EXTRACTION_SHELLCODE = 9,
-
+
PLUGX_PAYLOAD = 0x10,
PLUGX_CONFIG = 0x11,
-
+
EVILGRAB_PAYLOAD = 0x14,
EVILGRAB_DATA = 0x15,
-
+
SEDRECO_DATA = 0x20,
-
+
URSNIF_CONFIG = 0x24,
URSNIF_PAYLOAD = 0x25,
-
+
CERBER_CONFIG = 0x30,
- CERBER_PAYLOAD = 0x31
+ CERBER_PAYLOAD = 0x31,
+
+ QAKBOT_CONFIG = 0x38,
+ QAKBOT_PAYLOAD = 0x39,
+
+ DATADUMP = 0x66
};
HANDLE EvilGrabRegHandle;
diff --git a/CAPE/Debugger.c b/CAPE/Debugger.c
index 948b93b..a6fd924 100644
--- a/CAPE/Debugger.c
+++ b/CAPE/Debugger.c
@@ -28,20 +28,38 @@ along with this program.If not, see .
#define PIPEBUFSIZE 512
// eflags register
+#define FL_CF 0x00000001 // Carry Flag
+#define FL_PF 0x00000004 // Parity Flag
+#define FL_AF 0x00000010 // Auxiliary carry Flag
#define FL_ZF 0x00000040 // Zero Flag
-#define FL_TF 0x00000100 // Trap flag
-#define FL_RF 0x00010000 // Resume flag
+#define FL_SF 0x00000080 // Sign Flag
+#define FL_TF 0x00000100 // Trap Flag
+#define FL_IF 0x00000200 // Interrupt Enable
+#define FL_DF 0x00000400 // Direction Flag
+#define FL_OF 0x00000800 // Overflow Flag
+#define FL_IOPL_MASK 0x00003000 // I/O Privilege Level bitmask
+#define FL_IOPL_0 0x00000000 // IOPL == 0
+#define FL_IOPL_1 0x00001000 // IOPL == 1
+#define FL_IOPL_2 0x00002000 // IOPL == 2
+#define FL_IOPL_3 0x00003000 // IOPL == 3
+#define FL_NT 0x00004000 // Nested Task
+#define FL_RF 0x00010000 // Resume Flag
+#define FL_VM 0x00020000 // Virtual 8086 mode
+#define FL_AC 0x00040000 // Alignment Check
+#define FL_VIF 0x00080000 // Virtual Interrupt Flag
+#define FL_VIP 0x00100000 // Virtual Interrupt Pending
+#define FL_ID 0x00200000 // ID flag
//
// debug register DR7 bit fields
//
-typedef struct _DR7
+typedef struct _DR7
{
DWORD L0 : 1; //Local enable bp0
DWORD G0 : 1; //Global enable bp0
DWORD L1 : 1; //Local enable bp1
DWORD G1 : 1; //Global enable bp1
- DWORD L2 : 1; //Local enable bp2
+ DWORD L2 : 1; //Local enable bp2
DWORD G2 : 1; //Global enable bp2
DWORD L3 : 1; //Local enable bp3
DWORD G3 : 1; //Global enable bp3
@@ -107,6 +125,9 @@ unsigned int TrapIndex;
unsigned int DepthCount;
extern int operate_on_backtrace(ULONG_PTR _esp, ULONG_PTR _ebp, void *extra, int(*func)(void *, ULONG_PTR));
+#ifdef CAPE_TRACE
+extern BOOL TraceRunning;
+#endif
//**************************************************************************************
BOOL CountDepth(LPVOID* ReturnAddress, LPVOID Address)
@@ -122,9 +143,9 @@ BOOL CountDepth(LPVOID* ReturnAddress, LPVOID Address)
*ReturnAddress = Address;
return TRUE;
}
-
+
DepthCount++;
-
+
DoOutputDebugString("CountDepth: Address 0x%p, depthcount = %i.\n", Address, DepthCount);
return FALSE;
@@ -135,7 +156,7 @@ BOOL IsInTrackedRegions(PVOID Address)
//**************************************************************************************
{
PTRACKEDREGION CurrentTrackedRegion = TrackedRegionList;
-
+
if (TrackedRegionList == NULL)
return FALSE;
@@ -143,10 +164,10 @@ BOOL IsInTrackedRegions(PVOID Address)
{
if ((DWORD_PTR)Address >= (DWORD_PTR)CurrentTrackedRegion->BaseAddress && (DWORD_PTR)Address < ((DWORD_PTR)CurrentTrackedRegion->BaseAddress + (DWORD_PTR)CurrentTrackedRegion->RegionSize))
return TRUE;
-
+
CurrentTrackedRegion = CurrentTrackedRegion->NextTrackedRegion;
}
-
+
return FALSE;
}
@@ -155,7 +176,7 @@ PTRACKEDREGION GetTrackedRegion(PVOID Address)
//**************************************************************************************
{
PTRACKEDREGION CurrentTrackedRegion = TrackedRegionList;
-
+
if (Address == NULL)
{
DoOutputDebugString("GetTrackedRegion: NULL passed as argument - error.\n");
@@ -167,7 +188,7 @@ PTRACKEDREGION GetTrackedRegion(PVOID Address)
//DoOutputDebugString("GetTrackedRegion: failed to obtain initial tracked region list.\n");
return FALSE;
}
-
+
while (CurrentTrackedRegion)
{
if ((DWORD_PTR)Address >= (DWORD_PTR)CurrentTrackedRegion->BaseAddress && (DWORD_PTR)Address < ((DWORD_PTR)CurrentTrackedRegion->BaseAddress + (DWORD_PTR)CurrentTrackedRegion->RegionSize))
@@ -178,20 +199,20 @@ PTRACKEDREGION GetTrackedRegion(PVOID Address)
CurrentTrackedRegion = CurrentTrackedRegion->NextTrackedRegion;
}
-
+
//DoOutputDebugString("GetTrackedRegion: failed to find tracked region in list for address 0x%x.\n", Address);
-
+
return NULL;
}
//**************************************************************************************
PTRACKEDREGION CreateTrackedRegion()
//**************************************************************************************
-{
+{
if (TrackedRegionList == NULL)
{
TrackedRegionList = ((struct TrackedRegion*)malloc(sizeof(struct TrackedRegion)));
-
+
if (TrackedRegionList == NULL)
{
DoOutputDebugString("CreateTrackedRegion: failed to allocate memory for initial tracked region list.\n");
@@ -201,48 +222,48 @@ PTRACKEDREGION CreateTrackedRegion()
memset(TrackedRegionList, 0, sizeof(struct TrackedRegion));
}
- return TrackedRegionList;
+ return TrackedRegionList;
}
//**************************************************************************************
PTRACKEDREGION AddTrackedRegion(PVOID Address, SIZE_T RegionSize, ULONG Protect)
//**************************************************************************************
-{
+{
BOOL PageAlreadyTracked;
PTRACKEDREGION CurrentTrackedRegion, PreviousTrackedRegion;
unsigned int NumberOfTrackedRegions;
-
+
NumberOfTrackedRegions = 0;
PreviousTrackedRegion = NULL;
-
+
if (TrackedRegionList == NULL)
CreateTrackedRegion();
-
+
CurrentTrackedRegion = TrackedRegionList;
-
+
while (CurrentTrackedRegion)
{
if ((DWORD_PTR)Address >= (DWORD_PTR)CurrentTrackedRegion->BaseAddress && (DWORD_PTR)Address < ((DWORD_PTR)CurrentTrackedRegion->BaseAddress + (DWORD_PTR)CurrentTrackedRegion->RegionSize))
PageAlreadyTracked = TRUE;
else
PageAlreadyTracked = FALSE;
-
+
NumberOfTrackedRegions++;
-
+
PreviousTrackedRegion = CurrentTrackedRegion;
CurrentTrackedRegion = CurrentTrackedRegion->NextTrackedRegion;
- }
-
+ }
+
if (NumberOfTrackedRegions > 10)
DoOutputDebugString("AddTrackedRegion: DEBUG Warning - number of tracked regions %d.\n", NumberOfTrackedRegions);
-
+
if (GetPageAddress(Address) == GetPageAddress(TrackedRegionList))
{
DoOutputDebugString("AddTrackedRegion: Warning - attempting to track the page (0x%p) containing the tracked region list at 0x%p.\n", Address, TrackedRegionList);
-
+
return NULL;
}
-
+
if (PageAlreadyTracked)
{
DoOutputDebugString("AddTrackedRegion: Region at 0x%p already in list.\n", Address);
@@ -251,7 +272,7 @@ PTRACKEDREGION AddTrackedRegion(PVOID Address, SIZE_T RegionSize, ULONG Protect)
// We haven't found it in the linked list, so create a new one
CurrentTrackedRegion = PreviousTrackedRegion;
-
+
CurrentTrackedRegion->NextTrackedRegion = ((struct TrackedRegion*)malloc(sizeof(struct TrackedRegion)));
if (CurrentTrackedRegion->NextTrackedRegion == NULL)
@@ -259,38 +280,38 @@ PTRACKEDREGION AddTrackedRegion(PVOID Address, SIZE_T RegionSize, ULONG Protect)
DoOutputDebugString("AddTrackedRegion: Failed to allocate new tracked region struct.\n");
return NULL;
}
-
+
memset(CurrentTrackedRegion->NextTrackedRegion, 0, sizeof(struct TrackedRegion));
-
+
if (!VirtualQuery(Address, &CurrentTrackedRegion->MemInfo, sizeof(MEMORY_BASIC_INFORMATION)))
{
DoOutputErrorString("AddTrackedRegion: unable to query memory region 0x%p", Address);
return NULL;
}
-
+
CurrentTrackedRegion->BaseAddress = CurrentTrackedRegion->MemInfo.BaseAddress;
-
+
if (Address != CurrentTrackedRegion->BaseAddress)
CurrentTrackedRegion->ProtectAddress = Address;
-
+
if ((BYTE*)Address + RegionSize > (BYTE*)CurrentTrackedRegion->BaseAddress + CurrentTrackedRegion->MemInfo.RegionSize)
CurrentTrackedRegion->RegionSize = RegionSize;
else
CurrentTrackedRegion->RegionSize = CurrentTrackedRegion->MemInfo.RegionSize;
-
+
CurrentTrackedRegion->Protect = Protect;
-
+
//DoOutputDebugString("AddTrackedRegion: DEBUG - added region 0x%p to list at 0x%p - 0x%p.\n", Address, TrackedRegionList, (BYTE*)TrackedRegionList + NumberOfTrackedRegions*sizeof(TRACKEDREGION));
-
+
return CurrentTrackedRegion;
}
//**************************************************************************************
BOOL DropTrackedRegion(PTRACKEDREGION TrackedRegion)
//**************************************************************************************
-{
+{
PTRACKEDREGION CurrentTrackedRegion, PreviousTrackedRegion;
-
+
if (TrackedRegion == NULL)
{
DoOutputDebugString("DropTrackedRegion: NULL passed as argument - error.\n");
@@ -298,7 +319,7 @@ BOOL DropTrackedRegion(PTRACKEDREGION TrackedRegion)
}
PreviousTrackedRegion = NULL;
-
+
if (TrackedRegionList == NULL)
{
DoOutputDebugString("DropTrackedRegion: failed to obtain initial tracked region list.\n");
@@ -306,16 +327,16 @@ BOOL DropTrackedRegion(PTRACKEDREGION TrackedRegion)
}
CurrentTrackedRegion = TrackedRegionList;
-
+
while (CurrentTrackedRegion)
{
DoOutputDebugString("DropTrackedRegion: CurrentTrackedRegion 0x%x, BaseAddress 0x%x.\n", CurrentTrackedRegion, CurrentTrackedRegion->BaseAddress);
-
+
if (CurrentTrackedRegion == TrackedRegion)
{
// Clear any breakpoints in this region
ClearBreakpointsInRange(GetCurrentThreadId(), TrackedRegion->BaseAddress, TrackedRegion->RegionSize);
-
+
DoOutputDebugString("DropTrackedRegion: About to unlink.\n");
// Unlink this from the list and free the memory
if (PreviousTrackedRegion && CurrentTrackedRegion->NextTrackedRegion)
@@ -333,19 +354,19 @@ BOOL DropTrackedRegion(PTRACKEDREGION TrackedRegion)
DoOutputDebugString("DropTrackedRegion: removed pages 0x%x-0x%x from the head of the tracked region list.\n", TrackedRegion->BaseAddress, (DWORD_PTR)TrackedRegion->BaseAddress + TrackedRegion->RegionSize);
TrackedRegionList = NULL;
}
-
+
DoOutputDebugString("DropTrackedRegion: about to free the memory!\n");
free(CurrentTrackedRegion);
-
- return TRUE;
+
+ return TRUE;
}
-
+
PreviousTrackedRegion = CurrentTrackedRegion;
CurrentTrackedRegion = CurrentTrackedRegion->NextTrackedRegion;
}
-
+
DoOutputDebugString("DropTrackedRegion: failed to find tracked region in list.\n");
-
+
return FALSE;
}
@@ -357,15 +378,15 @@ BOOL ActivateGuardPages(PTRACKEDREGION TrackedRegion)
BOOL TrackedRegionFound = FALSE;
PTRACKEDREGION CurrentTrackedRegion;
PVOID TestAddress;
-
+
SIZE_T MatchingRegionSize;
if (TrackedRegion == NULL)
{
DoOutputDebugString("ActivateGuardPages: NULL passed as argument - error.\n");
return FALSE;
- }
-
+ }
+
if (TrackedRegionList == NULL)
{
DoOutputDebugString("ActivateGuardPages: Error - no tracked region list.\n");
@@ -373,27 +394,27 @@ BOOL ActivateGuardPages(PTRACKEDREGION TrackedRegion)
}
CurrentTrackedRegion = TrackedRegionList;
-
+
while (CurrentTrackedRegion)
{
//DoOutputDebugString("TrackedRegion->BaseAddress 0x%x, CurrentTrackedRegion->BaseAddress 0x%x.\n", TrackedRegion->BaseAddress, CurrentTrackedRegion->BaseAddress);
-
+
__try
{
TestAddress = CurrentTrackedRegion->BaseAddress;
}
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
DoOutputErrorString("ActivateGuardPages: Exception trying to access BaseAddres from tracked region at 0x%x", CurrentTrackedRegion);
return FALSE;
- }
-
+ }
+
if (TrackedRegion->BaseAddress == CurrentTrackedRegion->BaseAddress)
TrackedRegionFound = TRUE;
CurrentTrackedRegion = CurrentTrackedRegion->NextTrackedRegion;
}
-
+
if (!TrackedRegionFound)
{
DoOutputDebugString("ActivateGuardPages: failed to locate tracked region(s) in tracked region list.\n");
@@ -401,7 +422,7 @@ BOOL ActivateGuardPages(PTRACKEDREGION TrackedRegion)
}
MatchingRegionSize = VirtualQuery(TrackedRegion->BaseAddress, &TrackedRegion->MemInfo, sizeof(MEMORY_BASIC_INFORMATION));
-
+
if (!MatchingRegionSize)
{
DoOutputErrorString("ActivateGuardPages: failed to query tracked region(s) status in region 0x%x-0x%x", TrackedRegion->BaseAddress, (DWORD_PTR)TrackedRegion->BaseAddress + TrackedRegion->RegionSize);
@@ -409,21 +430,21 @@ BOOL ActivateGuardPages(PTRACKEDREGION TrackedRegion)
}
//DoOutputDebugString("ActivateGuardPages: BaseAddress 0x%x, AllocationBase 0x%x, AllocationProtect 0x%x, RegionSize 0x%x, State 0x%x, Protect 0x%x, Type 0x%x\n", TrackedRegion->MemInfo.BaseAddress, TrackedRegion->MemInfo.AllocationBase, TrackedRegion->MemInfo.AllocationProtect, TrackedRegion->MemInfo.RegionSize, TrackedRegion->MemInfo.State, TrackedRegion->MemInfo.Protect, TrackedRegion->MemInfo.Type);
-
+
if (MatchingRegionSize == TrackedRegion->RegionSize && TrackedRegion->MemInfo.Protect & PAGE_GUARD)
{
DoOutputDebugString("ActivateGuardPages: guard page(s) already set in region 0x%x-0x%x", TrackedRegion->BaseAddress, (DWORD_PTR)TrackedRegion->BaseAddress + TrackedRegion->RegionSize);
return FALSE;
}
-
+
if (!VirtualProtect(TrackedRegion->BaseAddress, TrackedRegion->RegionSize, TrackedRegion->Protect | PAGE_GUARD, &OldProtect))
{
DoOutputErrorString("ActivateGuardPages: failed to activate guard page(s) on region 0x%x size 0x%x", TrackedRegion->BaseAddress, TrackedRegion->RegionSize);
return FALSE;
}
-
+
//DoOutputDebugString("ActivateGuardPages: Activated guard page(s) on region 0x%x size 0x%x", TrackedRegion->BaseAddress, TrackedRegion->RegionSize);
-
+
return TRUE;
}
@@ -437,16 +458,16 @@ BOOL ActivateGuardPagesOnProtectedRange(PTRACKEDREGION TrackedRegion)
DWORD_PTR AddressOfPage;
SIZE_T Size;
PVOID TestAddress;
-
+
if (TrackedRegion == NULL)
{
DoOutputDebugString("ActivateGuardPagesOnProtectedRange: NULL passed as argument - error.\n");
return FALSE;
- }
-
+ }
+
if (!SystemInfo.dwPageSize)
GetSystemInfo(&SystemInfo);
-
+
if (!SystemInfo.dwPageSize)
{
DoOutputErrorString("ActivateGuardPagesOnProtectedRange: Failed to obtain system page size.\n");
@@ -460,27 +481,27 @@ BOOL ActivateGuardPagesOnProtectedRange(PTRACKEDREGION TrackedRegion)
}
CurrentTrackedRegion = TrackedRegionList;
-
+
while (CurrentTrackedRegion)
{
//DoOutputDebugString("TrackedRegion->BaseAddress 0x%x, CurrentTrackedRegion->BaseAddress 0x%x.\n", TrackedRegion->BaseAddress, CurrentTrackedRegion->BaseAddress);
-
+
__try
{
TestAddress = CurrentTrackedRegion->BaseAddress;
}
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
DoOutputErrorString("ActivateGuardPagesOnProtectedRange: Exception trying to access BaseAddress from tracked region at 0x%x", CurrentTrackedRegion);
return FALSE;
- }
+ }
if (TrackedRegion->BaseAddress == CurrentTrackedRegion->BaseAddress)
TrackedRegionFound = TRUE;
CurrentTrackedRegion = CurrentTrackedRegion->NextTrackedRegion;
}
-
+
if (!TrackedRegionFound)
{
DoOutputDebugString("ActivateGuardPagesOnProtectedRange: failed to locate tracked region(s) in tracked region list.\n");
@@ -498,17 +519,17 @@ BOOL ActivateGuardPagesOnProtectedRange(PTRACKEDREGION TrackedRegion)
DoOutputErrorString("ActivateGuardPagesOnProtectedRange: unable to query memory region 0x%x", TrackedRegion->BaseAddress);
return FALSE;
}
-
- AddressOfPage = ((DWORD_PTR)TrackedRegion->ProtectAddress/SystemInfo.dwPageSize)*SystemInfo.dwPageSize;
-
+
+ AddressOfPage = ((DWORD_PTR)TrackedRegion->ProtectAddress/SystemInfo.dwPageSize)*SystemInfo.dwPageSize;
+
Size = (BYTE*)TrackedRegion->ProtectAddress + TrackedRegion->RegionSize - (BYTE*)AddressOfPage;
-
+
if (!VirtualProtect((LPVOID)AddressOfPage, Size, TrackedRegion->Protect | PAGE_GUARD, &OldProtect))
{
DoOutputErrorString("ActivateGuardPagesOnProtectedRange: failed to activate guard page(s) on region 0x%x size 0x%x", AddressOfPage, Size);
return FALSE;
}
-
+
return TRUE;
}
@@ -521,19 +542,19 @@ BOOL DeactivateGuardPages(PTRACKEDREGION TrackedRegion)
BOOL TrackedRegionFound = FALSE;
PTRACKEDREGION CurrentTrackedRegion = TrackedRegionList;
PVOID TestAddress;
-
+
if (TrackedRegion == NULL)
{
DoOutputDebugString("DeactivateGuardPages: NULL passed as argument - error.\n");
return FALSE;
- }
+ }
if (TrackedRegionList == NULL)
{
DoOutputDebugString("DeactivateGuardPages: Error - no tracked region list.\n");
return FALSE;
}
-
+
//DoOutputDebugString("DeactivateGuardPages: DEBUG - tracked region list 0x%x, BaseAddress 0x%x.\n", CurrentTrackedRegion, CurrentTrackedRegion->BaseAddress);
while (CurrentTrackedRegion)
@@ -542,18 +563,18 @@ BOOL DeactivateGuardPages(PTRACKEDREGION TrackedRegion)
{
TestAddress = CurrentTrackedRegion->BaseAddress;
}
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
DoOutputErrorString("DeactivateGuardPages: Exception trying to access BaseAddres from tracked region at 0x%x", CurrentTrackedRegion);
return FALSE;
- }
+ }
if (TrackedRegion->BaseAddress == CurrentTrackedRegion->BaseAddress)
TrackedRegionFound = TRUE;
CurrentTrackedRegion = CurrentTrackedRegion->NextTrackedRegion;
}
-
+
if (!TrackedRegionFound)
{
DoOutputDebugString("DeactivateGuardPages: failed to locate tracked region(s) in tracked region list.\n");
@@ -561,13 +582,13 @@ BOOL DeactivateGuardPages(PTRACKEDREGION TrackedRegion)
}
MatchingRegionSize = VirtualQuery(TrackedRegion->BaseAddress, &TrackedRegion->MemInfo, sizeof(MEMORY_BASIC_INFORMATION));
-
+
if (!MatchingRegionSize)
{
DoOutputErrorString("DeactivateGuardPages: failed to query tracked region(s) status in region 0x%x-0x%x", TrackedRegion->BaseAddress, (DWORD_PTR)TrackedRegion->BaseAddress + TrackedRegion->RegionSize);
return FALSE;
}
-
+
if (MatchingRegionSize == TrackedRegion->RegionSize && !(TrackedRegion->MemInfo.Protect & PAGE_GUARD))
{
DoOutputDebugString("DeactivateGuardPages: guard page(s) not set in region 0x%x-0x%x", TrackedRegion->BaseAddress, (DWORD_PTR)TrackedRegion->BaseAddress + TrackedRegion->RegionSize);
@@ -579,9 +600,9 @@ BOOL DeactivateGuardPages(PTRACKEDREGION TrackedRegion)
DoOutputErrorString("DeactivateGuardPages: failed to deactivate guard page(s) on region 0x%x-0x%x", TrackedRegion->BaseAddress, (DWORD_PTR)TrackedRegion->BaseAddress + TrackedRegion->RegionSize);
return FALSE;
}
-
+
DoOutputDebugString("DeactivateGuardPages: DEBUG: Deactivated guard page(s) on region 0x%x-0x%x", TrackedRegion->BaseAddress, (DWORD_PTR)TrackedRegion->BaseAddress + TrackedRegion->RegionSize);
-
+
return TRUE;
}
@@ -594,40 +615,40 @@ BOOL ActivateSurroundingGuardPages(PTRACKEDREGION TrackedRegion)
BOOL TrackedRegionFound = FALSE;
PTRACKEDREGION CurrentTrackedRegion = TrackedRegionList;
PVOID TestAddress;
-
+
if (TrackedRegionList == NULL)
- {
+ {
DoOutputDebugString("ActivateSurroundingGuardPages: Error - TrackedRegionList NULL.\n");
return 0;
}
-
+
if (!SystemInfo.dwPageSize)
GetSystemInfo(&SystemInfo);
-
+
if (!SystemInfo.dwPageSize)
{
DoOutputErrorString("ActivateSurroundingGuardPages: Failed to obtain system page size.\n");
return 0;
}
-
+
while (CurrentTrackedRegion)
{
__try
{
TestAddress = CurrentTrackedRegion->BaseAddress;
}
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
DoOutputErrorString("ActivateSurroundingGuardPages: Exception trying to access BaseAddres from tracked region at 0x%x", CurrentTrackedRegion);
return FALSE;
- }
+ }
if (TrackedRegion->BaseAddress == CurrentTrackedRegion->BaseAddress)
TrackedRegionFound = TRUE;
CurrentTrackedRegion = CurrentTrackedRegion->NextTrackedRegion;
}
-
+
if (!TrackedRegionFound)
{
DoOutputDebugString("ActivateSurroundingGuardPages: Failed to locate tracked region(s) in tracked region list.\n");
@@ -635,7 +656,7 @@ BOOL ActivateSurroundingGuardPages(PTRACKEDREGION TrackedRegion)
}
if (!TrackedRegion->LastAccessAddress)
- {
+ {
DoOutputDebugString("ActivateSurroundingGuardPages: Error - Last access address not set.\n");
return 0;
}
@@ -645,30 +666,30 @@ BOOL ActivateSurroundingGuardPages(PTRACKEDREGION TrackedRegion)
DoOutputDebugString("ActivateSurroundingGuardPages: Last access address 0x%x not within tracked region at 0x%x.\n", TrackedRegion->LastAccessAddress, TrackedRegion->BaseAddress);
return FALSE;
}
-
- AddressOfPage = ((DWORD_PTR)TrackedRegion->LastAccessAddress/SystemInfo.dwPageSize)*SystemInfo.dwPageSize;
-
+
+ AddressOfPage = ((DWORD_PTR)TrackedRegion->LastAccessAddress/SystemInfo.dwPageSize)*SystemInfo.dwPageSize;
+
if (!VirtualQuery(TrackedRegion->BaseAddress, &TrackedRegion->MemInfo, sizeof(MEMORY_BASIC_INFORMATION)))
{
DoOutputErrorString("ProtectionHandler: unable to query memory region 0x%x", TrackedRegion->BaseAddress);
return FALSE;
}
-
- for
+
+ for
(
- PagePointer = ((DWORD_PTR)TrackedRegion->BaseAddress/SystemInfo.dwPageSize)*SystemInfo.dwPageSize;
+ PagePointer = ((DWORD_PTR)TrackedRegion->BaseAddress/SystemInfo.dwPageSize)*SystemInfo.dwPageSize;
(BYTE*)PagePointer + SystemInfo.dwPageSize < (BYTE*)TrackedRegion->BaseAddress + TrackedRegion->RegionSize;
PagePointer += SystemInfo.dwPageSize
)
{
- // We skip the initial page if a switch to breakpoints has occured
+ // We skip the initial page if a switch to breakpoints has occurred
if (PagePointer == (DWORD_PTR)TrackedRegion->BaseAddress && TrackedRegion->BreakpointsSet)
PagePointer += SystemInfo.dwPageSize;
-
+
if (PagePointer != AddressOfPage)
{
RetVal = VirtualProtect((LPVOID)PagePointer, SystemInfo.dwPageSize, TrackedRegion->Protect | PAGE_GUARD, &OldProtect);
-
+
if (!RetVal)
{
DoOutputDebugString("ActivateSurroundingGuardPages: Failed to activate page guard on tracked region at 0x%x.\n", PagePointer);
@@ -684,20 +705,20 @@ BOOL ActivateSurroundingGuardPages(PTRACKEDREGION TrackedRegion)
PTHREADBREAKPOINTS GetThreadBreakpoints(DWORD ThreadId)
//**************************************************************************************
{
- DWORD CurrentThreadId;
-
+ DWORD CurrentThreadId;
+
PTHREADBREAKPOINTS CurrentThreadBreakpoint = MainThreadBreakpointList;
while (CurrentThreadBreakpoint)
{
CurrentThreadId = MyGetThreadId(CurrentThreadBreakpoint->ThreadHandle);
-
+
if (CurrentThreadId == ThreadId)
return CurrentThreadBreakpoint;
else
CurrentThreadBreakpoint = CurrentThreadBreakpoint->NextThreadBreakpoints;
}
-
+
return NULL;
}
@@ -705,20 +726,20 @@ PTHREADBREAKPOINTS GetThreadBreakpoints(DWORD ThreadId)
HANDLE GetThreadHandle(DWORD ThreadId)
//**************************************************************************************
{
- DWORD CurrentThreadId;
-
+ DWORD CurrentThreadId;
+
PTHREADBREAKPOINTS CurrentThreadBreakpoint = MainThreadBreakpointList;
while (CurrentThreadBreakpoint)
{
CurrentThreadId = MyGetThreadId(CurrentThreadBreakpoint->ThreadHandle);
-
+
if (CurrentThreadId == ThreadId)
return CurrentThreadBreakpoint->ThreadHandle;
else
CurrentThreadBreakpoint = CurrentThreadBreakpoint->NextThreadBreakpoints;
}
-
+
return NULL;
}
@@ -730,61 +751,61 @@ PTHREADBREAKPOINTS CreateThreadBreakpoints(DWORD ThreadId)
PTHREADBREAKPOINTS CurrentThreadBreakpoint, PreviousThreadBreakpoint;
PreviousThreadBreakpoint = NULL;
-
+
if (MainThreadBreakpointList == NULL)
{
MainThreadBreakpointList = ((struct ThreadBreakpoints*)malloc(sizeof(struct ThreadBreakpoints)));
-
+
if (MainThreadBreakpointList == NULL)
{
DoOutputDebugString("CreateThreadBreakpoints: failed to allocate memory for initial thread breakpoint list.\n");
return NULL;
}
-
+
memset(MainThreadBreakpointList, 0, sizeof(struct ThreadBreakpoints));
-
+
MainThreadBreakpointList->ThreadId = MainThreadId;
}
CurrentThreadBreakpoint = MainThreadBreakpointList;
-
+
while (CurrentThreadBreakpoint)
- {
+ {
if (CurrentThreadBreakpoint->ThreadHandle && MyGetThreadId(CurrentThreadBreakpoint->ThreadHandle) == ThreadId)
{
//It already exists - shouldn't happen
DoOutputDebugString("CreateThreadBreakpoints error: found an existing thread breakpoint list for ThreadId 0x%x\n", ThreadId);
return NULL;
}
-
+
if ((CurrentThreadBreakpoint->ThreadId) == ThreadId)
{
// We have our thread breakpoint list
- break;
+ break;
}
-
+
PreviousThreadBreakpoint = CurrentThreadBreakpoint;
CurrentThreadBreakpoint = CurrentThreadBreakpoint->NextThreadBreakpoints;
}
-
+
if (!CurrentThreadBreakpoint)
{
// We haven't found it in the linked list, so create a new one
CurrentThreadBreakpoint = PreviousThreadBreakpoint;
-
+
CurrentThreadBreakpoint->NextThreadBreakpoints = ((struct ThreadBreakpoints*)malloc(sizeof(struct ThreadBreakpoints)));
-
+
if (CurrentThreadBreakpoint->NextThreadBreakpoints == NULL)
{
DoOutputDebugString("CreateThreadBreakpoints: Failed to allocate new thread breakpoints.\n");
return NULL;
}
-
+
memset(CurrentThreadBreakpoint->NextThreadBreakpoints, 0, sizeof(struct ThreadBreakpoints));
-
+
CurrentThreadBreakpoint = CurrentThreadBreakpoint->NextThreadBreakpoints;
}
-
+
if (ThreadId == GetCurrentThreadId())
{
if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &CurrentThreadBreakpoint->ThreadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0)
@@ -797,7 +818,7 @@ PTHREADBREAKPOINTS CreateThreadBreakpoints(DWORD ThreadId)
else
{
CurrentThreadBreakpoint->ThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, ThreadId);
-
+
if (CurrentThreadBreakpoint->ThreadHandle == NULL)
{
DoOutputDebugString("CreateThreadBreakpoints: Failed to open thread and get a handle.\n");
@@ -805,15 +826,15 @@ PTHREADBREAKPOINTS CreateThreadBreakpoints(DWORD ThreadId)
return NULL;
}
}
-
+
CurrentThreadBreakpoint->ThreadId = ThreadId;
-
+
for (Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
{
CurrentThreadBreakpoint->BreakpointInfo[Register].Register = Register;
CurrentThreadBreakpoint->BreakpointInfo[Register].ThreadHandle = CurrentThreadBreakpoint->ThreadHandle;
}
-
+
return CurrentThreadBreakpoint;
}
@@ -821,37 +842,35 @@ PTHREADBREAKPOINTS CreateThreadBreakpoints(DWORD ThreadId)
BOOL InitNewThreadBreakpoints(DWORD ThreadId)
//**************************************************************************************
{
- //DoOutputDebugString("InitNewThreadBreakpoints: Initialising breakpoints for thread %d.\n", ThreadId);
- //return TRUE;
PTHREADBREAKPOINTS NewThreadBreakpoints;
-
+
if (MainThreadBreakpointList == NULL)
{
DoOutputDebugString("InitNewThreadBreakpoints: Failed to create thread breakpoints struct.\n");
- return FALSE;
+ return FALSE;
}
-
+
NewThreadBreakpoints = CreateThreadBreakpoints(ThreadId);
-
+
if (NewThreadBreakpoints == NULL)
{
DoOutputDebugString("InitNewThreadBreakpoints: Cannot create new thread breakpoints.\n");
return FALSE;
}
-
+
if (NewThreadBreakpoints->ThreadHandle == NULL)
{
DoOutputDebugString("InitNewThreadBreakpoints error: main thread handle not set.\n");
- return FALSE;
+ return FALSE;
}
-
+
for (unsigned int Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
{
if (!MainThreadBreakpointList->BreakpointInfo[Register].Address)
continue;
-
+
NewThreadBreakpoints->BreakpointInfo[Register] = MainThreadBreakpointList->BreakpointInfo[Register];
-
+
if (!NewThreadBreakpoints->BreakpointInfo[Register].Address)
DoOutputDebugString("InitNewThreadBreakpoints error: failed to copy the bleeding breakpoint struct!\n");
@@ -861,7 +880,7 @@ BOOL InitNewThreadBreakpoints(DWORD ThreadId)
return FALSE;
}
}
-
+
return TRUE;
}
@@ -869,9 +888,9 @@ BOOL InitNewThreadBreakpoints(DWORD ThreadId)
BOOL GetNextAvailableBreakpoint(DWORD ThreadId, unsigned int* Register)
//**************************************************************************************
{
- DWORD CurrentThreadId;
+ DWORD CurrentThreadId;
unsigned int i;
-
+
PTHREADBREAKPOINTS CurrentThreadBreakpoint = MainThreadBreakpointList;
if (CurrentThreadBreakpoint == NULL)
@@ -879,11 +898,11 @@ BOOL GetNextAvailableBreakpoint(DWORD ThreadId, unsigned int* Register)
DoOutputDebugString("GetNextAvailableBreakpoint: MainThreadBreakpointList NULL.\n");
return FALSE;
}
-
+
while (CurrentThreadBreakpoint)
{
CurrentThreadId = MyGetThreadId(CurrentThreadBreakpoint->ThreadHandle);
-
+
if (CurrentThreadId == ThreadId)
{
for (i=0; i < NUMBER_OF_DEBUG_REGISTERS; i++)
@@ -892,13 +911,13 @@ BOOL GetNextAvailableBreakpoint(DWORD ThreadId, unsigned int* Register)
{
*Register = i;
return TRUE;
- }
+ }
}
}
-
+
CurrentThreadBreakpoint = CurrentThreadBreakpoint->NextThreadBreakpoints;
}
-
+
return FALSE;
}
@@ -906,17 +925,17 @@ BOOL GetNextAvailableBreakpoint(DWORD ThreadId, unsigned int* Register)
BOOL ContextGetNextAvailableBreakpoint(PCONTEXT Context, unsigned int* Register)
//**************************************************************************************
{
- unsigned int i;
+ unsigned int i;
PTHREADBREAKPOINTS CurrentThreadBreakpoint;
-
+
CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("ContextGetNextAvailableBreakpoint: Creating new thread breakpoints for thread %d.\n", GetCurrentThreadId());
CurrentThreadBreakpoint = CreateThreadBreakpoints(GetCurrentThreadId());
}
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("ContextGetNextAvailableBreakpoint: Cannot create new thread breakpoints - FATAL.\n");
@@ -932,7 +951,7 @@ BOOL ContextGetNextAvailableBreakpoint(PCONTEXT Context, unsigned int* Register)
}
}
- return FALSE;
+ return FALSE;
}
//**************************************************************************************
@@ -944,24 +963,24 @@ void DebugOutputThreadBreakpoints()
PBREAKPOINTINFO pBreakpointInfo;
CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
-
+
for (Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
{
pBreakpointInfo = &(CurrentThreadBreakpoint->BreakpointInfo[Register]);
-
+
if (pBreakpointInfo == NULL)
{
DoOutputDebugString("DebugOutputThreadBreakpoints: Can't get BreakpointInfo - FATAL.\n");
}
- DoOutputDebugString("Callback = 0x%x, Address = 0x%x, Size = 0x%x, Register = %i, ThreadHandle = 0x%x, Type = 0x%x\n",
- pBreakpointInfo->Callback,
- pBreakpointInfo->Address,
- pBreakpointInfo->Size,
- pBreakpointInfo->Register,
- pBreakpointInfo->ThreadHandle,
+ DoOutputDebugString("Callback = 0x%x, Address = 0x%x, Size = 0x%x, Register = %i, ThreadHandle = 0x%x, Type = 0x%x\n",
+ pBreakpointInfo->Callback,
+ pBreakpointInfo->Address,
+ pBreakpointInfo->Size,
+ pBreakpointInfo->Register,
+ pBreakpointInfo->ThreadHandle,
pBreakpointInfo->Type);
- }
+ }
}
//**************************************************************************************
@@ -969,11 +988,24 @@ void ShowStack(DWORD_PTR StackPointer, unsigned int NumberOfRecords)
//**************************************************************************************
{
unsigned int i;
-
+
for (i=0; iExceptionRecord->ExceptionCode==EXCEPTION_SINGLE_STEP)
- {
+ {
BOOL BreakpointFlag;
PBREAKPOINTINFO pBreakpointInfo;
PTHREADBREAKPOINTS CurrentThreadBreakpoint;
@@ -998,7 +1030,7 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
{
DoOutputDebugString("CAPEExceptionFilter: Can't get thread breakpoints - FATAL.\n");
return EXCEPTION_CONTINUE_SEARCH;
- }
+ }
// Test Dr6 to see if this is a breakpoint
BreakpointFlag = FALSE;
@@ -1009,60 +1041,60 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
BreakpointFlag = TRUE;
}
}
-
+
+
// If not it's a single-step
if (!BreakpointFlag)
- {
+ {
if (SingleStepHandler)
SingleStepHandler(ExceptionInfo);
else if (TrapIndex)
// this is from a 'StepOver' function
{
DoOutputDebugString("CAPEExceptionFilter: Stepping over execution breakpoint to: 0x%x\n", ExceptionInfo->ExceptionRecord->ExceptionAddress);
-
+
pBreakpointInfo = &(CurrentThreadBreakpoint->BreakpointInfo[TrapIndex-1]);
-
+
ResumeAfterExecutionBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo);
}
else
- {
- DoOutputDebugString("CAPEExceptionFilter: Error, unhandled single-step exception at: 0x%x\n", ExceptionInfo->ExceptionRecord->ExceptionAddress);
+ // pass it on
return EXCEPTION_CONTINUE_SEARCH;
- }
-
+
return EXCEPTION_CONTINUE_EXECUTION;
}
-
+
if (TrapIndex)
- {
DoOutputDebugString("CAPEExceptionFilter: Anomaly detected: Trap index set on non-single-step: %d\n", TrapIndex);
- }
-
+
+#ifdef CAPE_TRACE
+ if (!TraceRunning)
+#endif
DoOutputDebugString("CAPEExceptionFilter: breakpoint hit by instruction at 0x%p\n", ExceptionInfo->ExceptionRecord->ExceptionAddress);
-
+
for (bp = 0; bp < NUMBER_OF_DEBUG_REGISTERS; bp++)
{
if (ExceptionInfo->ContextRecord->Dr6 & (DWORD_PTR)(1 << bp))
{
pBreakpointInfo = &(CurrentThreadBreakpoint->BreakpointInfo[bp]);
-
+
if (pBreakpointInfo == NULL)
{
DoOutputDebugString("CAPEExceptionFilter: Can't get BreakpointInfo - FATAL.\n");
return EXCEPTION_CONTINUE_EXECUTION;
- }
-
- if (pBreakpointInfo->Register == bp)
+ }
+
+ if (pBreakpointInfo->Register == bp)
{
if (bp == 0 && ((DWORD_PTR)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr0))
DoOutputDebugString("CAPEExceptionFilter: Anomaly detected! bp0 address (0x%x) different to BreakpointInfo (0x%x)!\n", ExceptionInfo->ContextRecord->Dr0, pBreakpointInfo->Address);
-
+
if (bp == 1 && ((DWORD_PTR)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr1))
DoOutputDebugString("CAPEExceptionFilter: Anomaly detected! bp1 address (0x%x) different to BreakpointInfo (0x%x)!\n", ExceptionInfo->ContextRecord->Dr1, pBreakpointInfo->Address);
if (bp == 2 && ((DWORD_PTR)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr2))
DoOutputDebugString("CAPEExceptionFilter: Anomaly detected! bp2 address (0x%x) different to BreakpointInfo (0x%x)!\n", ExceptionInfo->ContextRecord->Dr2, pBreakpointInfo->Address);
-
+
if (bp == 3 && ((DWORD_PTR)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr3))
DoOutputDebugString("CAPEExceptionFilter: Anomaly detected! bp3 address (0x%x) different to BreakpointInfo (0x%x)!\n", ExceptionInfo->ContextRecord->Dr3, pBreakpointInfo->Address);
#ifndef _WIN64
@@ -1071,7 +1103,7 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE0 == BP_WRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
{
DoOutputDebugString("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->Callback);
}
else
@@ -1085,7 +1117,7 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE1 == BP_WRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
{
DoOutputDebugString("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->Callback);
}
else
@@ -1099,7 +1131,7 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE2 == BP_WRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
{
DoOutputDebugString("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->Callback);
}
else
@@ -1113,7 +1145,7 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE3 == BP_WRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
{
DoOutputDebugString("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->Callback);
}
else
@@ -1132,25 +1164,25 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
DoOutputDebugString("CAPEExceptionFilter: Can't get callback - FATAL.\n");
return EXCEPTION_CONTINUE_EXECUTION;
}
-
+
Handler = (BREAKPOINT_HANDLER)pBreakpointInfo->Callback;
-
+
// Invoke the handler
Handler(pBreakpointInfo, ExceptionInfo);
-
+
return EXCEPTION_CONTINUE_EXECUTION;
}
// Page guard violations generate STATUS_GUARD_PAGE_VIOLATION
else if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
- {
+ {
if (ExceptionInfo->ExceptionRecord->NumberParameters < 2)
{
DoOutputDebugString("CAPEExceptionFilter: Guard page exception with missing parameters, passing.\n");
- return EXCEPTION_CONTINUE_SEARCH;
+ return EXCEPTION_CONTINUE_SEARCH;
}
-
+
//DoOutputDebugString("Entering CAPEExceptionFilter: guarded page access at 0x%x by 0x%x\n", ExceptionInfo->ExceptionRecord->ExceptionInformation[1], ExceptionInfo->ExceptionRecord->ExceptionAddress);
-
+
if (TrackedRegion = GetTrackedRegion((PVOID)ExceptionInfo->ExceptionRecord->ExceptionInformation[1]))
{
if (is_address_in_ntdll((ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress))
@@ -1159,10 +1191,10 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
{
DoOutputDebugString("CAPEExceptionFilter: Failed to re-activate page guard on tracked region around 0x%x touched by ntdll.\n", ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
}
-
+
return EXCEPTION_CONTINUE_EXECUTION;
}
-
+
if (GuardPageHandler)
{
if (GuardPageHandler(ExceptionInfo))
@@ -1182,64 +1214,52 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
return EXCEPTION_CONTINUE_SEARCH;
}
}
- //else if (ExceptionInfo->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C)
- //{
- // // This could be useful output
- // // TODO: find string buffer(s) and send info to DoOutputDebugString
- // return EXCEPTION_CONTINUE_SEARCH;
- //}
- else if (!VECTORED_HANDLER && OriginalExceptionHandler)
+ else if (ExceptionInfo->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C)
{
- if ((ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress >= g_our_dll_base && (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress < (g_our_dll_base + g_our_dll_size))
- {
- // This is a CAPE (or Cuckoo) exception
- return EXCEPTION_EXECUTE_HANDLER;
- }
-
- // As it's not a bp, and the sample has registered its own handler
- // we return EXCEPTION_EXECUTE_HANDLER
- DoOutputDebugString("CAPEExceptionFilter: Non-breakpoint exception caught, passing to sample's handler.\n");
- SetUnhandledExceptionFilter(OriginalExceptionHandler);
- return EXCEPTION_EXECUTE_HANDLER;
+ // This could be useful output
+ // TODO: find string buffer(s) and send info to DoOutputDebugString
+ //DoOutputDebugString("CAPEExceptionFilter: DBG_PRINTEXCEPTION_C at 0x%x (0x%x).\n", ExceptionInfo->ExceptionRecord->ExceptionInformation[1], ExceptionInfo->ExceptionRecord->ExceptionInformation[0]);
+ return EXCEPTION_CONTINUE_SEARCH;
}
else if (VECTORED_HANDLER && SampleVectoredHandler)
- {
+ {
// As it's not a bp and the sample has registered its own handler
//DoOutputDebugString("CAPEExceptionFilter: Non-breakpoint exception caught, passing to sample's vectored handler.\n");
- SampleVectoredHandler(ExceptionInfo);
+ return SampleVectoredHandler(ExceptionInfo);
}
-
+
if ((ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress >= g_our_dll_base && (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress < (g_our_dll_base + g_our_dll_size))
{
// This is a CAPE (or Cuckoo) exception
DoOutputDebugString("CAPEExceptionFilter: Exception 0x%x caught at RVA 0x%x in capemon caught accessing 0x%x (expected in memory scans), passing to next handler.\n", ExceptionInfo->ExceptionRecord->ExceptionCode, (BYTE*)ExceptionInfo->ExceptionRecord->ExceptionAddress - g_our_dll_base, ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
return EXCEPTION_CONTINUE_SEARCH;
}
-
+
// Some other exception occurred. Pass it to next handler.
//DllRVA = 0;
//if (ExceptionInfo->ExceptionRecord->ExceptionAddress)
// DllName = convert_address_to_dll_name_and_offset((ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress, &DllRVA);
//else
// DllName = "unknown";
- //
+ //
//DoOutputDebugString("CAPEExceptionFilter: Exception 0x%x caught at 0x%x accessing 0x%x (RVA 0x%x in %s) passing.\n", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress, ExceptionInfo->ExceptionRecord->ExceptionInformation[1], DllRVA, DllName);
return EXCEPTION_CONTINUE_SEARCH;
}
//**************************************************************************************
-BOOL ContextSetDebugRegister
+BOOL ContextSetDebugRegisterEx
//**************************************************************************************
(
PCONTEXT Context,
int Register,
int Size,
LPVOID Address,
- DWORD Type
+ DWORD Type,
+ BOOL NoSetThreadContext
)
{
DWORD Length;
-#ifdef _WIN64
+#ifdef _WIN64
PTHREADBREAKPOINTS CurrentThreadBreakpoint;
#endif
@@ -1247,7 +1267,7 @@ BOOL ContextSetDebugRegister
PDWORD_PTR Dr1 = &(Context->Dr1);
PDWORD_PTR Dr2 = &(Context->Dr2);
PDWORD_PTR Dr3 = &(Context->Dr3);
- PDR7 Dr7 = (PDR7)&(Context->Dr7);
+ PDR7 Dr7 = (PDR7)&(Context->Dr7);
if ((unsigned int)Type > 3)
{
@@ -1266,15 +1286,13 @@ BOOL ContextSetDebugRegister
DoOutputDebugString("ContextSetDebugRegister: %d is an invalid register, must be 0-3.\n", Register);
return FALSE;
}
-
+
if (Size < 0 || Size > 8)
{
DoOutputDebugString("ContextSetDebugRegister: %d is an invalid Size, must be 1, 2, 4 or 8.\n", Size);
return FALSE;
}
- DoOutputDebugString("ContextSetDebugRegister: Setting breakpoint %i within Context, Size=0x%x, Address=0x%p and Type=0x%x.\n", Register, Size, Address, Type);
-
Length = LengthMask[Size];
// intel spec requires 0 for bp on execution
@@ -1284,43 +1302,46 @@ BOOL ContextSetDebugRegister
#ifndef _WIN64
if (Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)Address))
WoW64PatchBreakpoint(Register);
-#endif
-
+#endif
+
if (Register == 0)
{
*Dr0 = (DWORD_PTR)Address;
Dr7->LEN0 = Length;
Dr7->RWE0 = Type;
- Dr7->L0 = 1;
+ Dr7->L0 = 1;
}
else if (Register == 1)
{
*Dr1 = (DWORD_PTR)Address;
Dr7->LEN1 = Length;
Dr7->RWE1 = Type;
- Dr7->L1 = 1;
+ Dr7->L1 = 1;
}
else if (Register == 2)
{
*Dr2 = (DWORD_PTR)Address;
Dr7->LEN2 = Length;
Dr7->RWE2 = Type;
- Dr7->L2 = 1;
+ Dr7->L2 = 1;
}
else if (Register == 3)
{
*Dr3 = (DWORD_PTR)Address;
Dr7->LEN3 = Length;
Dr7->RWE3 = Type;
- Dr7->L3 = 1;
+ Dr7->L3 = 1;
}
-
+
Dr7->LE = 1;
Context->Dr6 = 0;
-
-#ifdef _WIN64
+
+#ifdef _WIN64
+ if (NoSetThreadContext)
+ return TRUE;
+
CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("ContextSetDebugRegister: No breakpoints found for current thread %d.\n", GetCurrentThreadId());
@@ -1334,19 +1355,31 @@ BOOL ContextSetDebugRegister
}
Context->ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
+
if (!SetThreadContext(CurrentThreadBreakpoint->ThreadHandle, Context))
{
DoOutputErrorString("ContextSetDebugRegister: SetThreadContext failed");
return FALSE;
- }
- else
- DoOutputDebugString("ContextSetDebugRegister: SetThreadContext success.\n");
+ }
#endif
return TRUE;
}
+//**************************************************************************************
+BOOL ContextSetDebugRegister
+//**************************************************************************************
+(
+ PCONTEXT Context,
+ int Register,
+ int Size,
+ LPVOID Address,
+ DWORD Type
+)
+{
+ return ContextSetDebugRegisterEx(Context, Register, Size, Address, Type, FALSE);
+}
+
//**************************************************************************************
BOOL SetDebugRegister
//**************************************************************************************
@@ -1384,7 +1417,7 @@ BOOL SetDebugRegister
DoOutputDebugString("SetDebugRegister: %d is an invalid register, must be 0-3.\n", Register);
return FALSE;
}
-
+
if (Size < 0 || Size > 8)
{
DoOutputDebugString("SetDebugRegister: %d is an invalid Size, must be 1, 2, 4 or 8.\n", Size);
@@ -1392,9 +1425,9 @@ BOOL SetDebugRegister
}
DoOutputDebugString("SetDebugRegister: Setting breakpoint %i hThread=0x%x, Size=0x%x, Address=0x%p and Type=0x%x.\n", Register, hThread, Size, Address, Type);
-
+
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
+
if (!GetThreadContext(hThread, &Context))
{
DoOutputErrorString("SetDebugRegister: GetThreadContext failed (thread handle 0x%x)", hThread);
@@ -1410,37 +1443,37 @@ BOOL SetDebugRegister
#ifndef _WIN64
if (Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)Address))
WoW64PatchBreakpoint(Register);
-#endif
-
+#endif
+
if (Register == 0)
{
*Dr0 = (DWORD_PTR)Address;
Dr7->LEN0 = Length;
Dr7->RWE0 = Type;
- Dr7->L0 = 1;
+ Dr7->L0 = 1;
}
else if (Register == 1)
{
*Dr1 = (DWORD_PTR)Address;
Dr7->LEN1 = Length;
Dr7->RWE1 = Type;
- Dr7->L1 = 1;
+ Dr7->L1 = 1;
}
else if (Register == 2)
{
*Dr2 = (DWORD_PTR)Address;
Dr7->LEN2 = Length;
Dr7->RWE2 = Type;
- Dr7->L2 = 1;
+ Dr7->L2 = 1;
}
else if (Register == 3)
{
*Dr3 = (DWORD_PTR)Address;
Dr7->LEN3 = Length;
Dr7->RWE3 = Type;
- Dr7->L3 = 1;
+ Dr7->L3 = 1;
}
-
+
Dr7->LE = 1;
Context.Dr6 = 0;
@@ -1451,24 +1484,24 @@ BOOL SetDebugRegister
DoOutputErrorString("SetDebugRegister: SetThreadContext failed");
return FALSE;
}
-
+
return TRUE;
}
//**************************************************************************************
BOOL ContextCheckDebugRegisters(PCONTEXT Context)
//**************************************************************************************
-{
+{
PDR7 Dr7;
-
+
if (!Context)
{
DoOutputDebugString("CheckDebugRegisters - no context supplied.\n");
return FALSE;
}
-
+
Dr7 = (PDR7)&(Context->Dr7);
-
+
DoOutputDebugString("Checking breakpoints\n");
DoOutputDebugString("Dr0 0x%x, Dr7->LEN0 %i, Dr7->RWE0 %i, Dr7->L0 %i\n", Context->Dr0, Dr7->LEN0, Dr7->RWE0, Dr7->L0);
DoOutputDebugString("Dr1 0x%x, Dr7->LEN1 %i, Dr7->RWE1 %i, Dr7->L1 %i\n", Context->Dr1, Dr7->LEN1, Dr7->RWE1, Dr7->L1);
@@ -1489,7 +1522,7 @@ BOOL CheckDebugRegisters(HANDLE hThread, PCONTEXT pContext)
PDWORD_PTR Dr2 = &Context.Dr2;
PDWORD_PTR Dr3 = &Context.Dr3;
PDR7 Dr7 = (PDR7)&(Context.Dr7);
-
+
if (!hThread && !pContext)
{
DoOutputDebugString("CheckDebugRegisters - required arguments missing.\n");
@@ -1507,9 +1540,9 @@ BOOL CheckDebugRegisters(HANDLE hThread, PCONTEXT pContext)
{
DoOutputDebugString("CheckDebugRegisters - failed to get thread context.\n");
return FALSE;
- }
+ }
}
-
+
DoOutputDebugString("Checking breakpoints\n");
DoOutputDebugString("*Dr0 0x%x, Dr7->LEN0 %i, Dr7->RWE0 %i, Dr7->L0 %i\n", *Dr0, Dr7->LEN0, Dr7->RWE0, Dr7->L0);
DoOutputDebugString("*Dr1 0x%x, Dr7->LEN1 %i, Dr7->RWE1 %i, Dr7->L1 %i\n", *Dr1, Dr7->LEN1, Dr7->RWE1, Dr7->L1);
@@ -1524,17 +1557,17 @@ BOOL CheckDebugRegisters(HANDLE hThread, PCONTEXT pContext)
BOOL ContextClearAllBreakpoints(PCONTEXT Context)
//**************************************************************************************
{
- unsigned int i;
+ unsigned int i;
PTHREADBREAKPOINTS CurrentThreadBreakpoint;
-
+
CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("ContextClearAllBreakpoints: No breakpoints found for current thread %d.\n", GetCurrentThreadId());
return FALSE;
}
-
+
for (i=0; i < NUMBER_OF_DEBUG_REGISTERS; i++)
{
CurrentThreadBreakpoint->BreakpointInfo[i].Register = 0;
@@ -1551,7 +1584,7 @@ BOOL ContextClearAllBreakpoints(PCONTEXT Context)
Context->Dr6 = 0;
Context->Dr7 = 0;
-#ifdef _WIN64
+#ifdef _WIN64
if (CurrentThreadBreakpoint->ThreadHandle == NULL)
{
DoOutputDebugString("ContextClearAllBreakpoints: No thread handle found in breakpoints found for current thread %d.\n", GetCurrentThreadId());
@@ -1559,12 +1592,12 @@ BOOL ContextClearAllBreakpoints(PCONTEXT Context)
}
Context->ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
+
if (!SetThreadContext(CurrentThreadBreakpoint->ThreadHandle, Context))
{
DoOutputErrorString("ContextClearAllBreakpoints: SetThreadContext failed");
return FALSE;
- }
+ }
else
DoOutputDebugString("ContextClearAllBreakpoints: SetThreadContext success.\n");
#endif
@@ -1577,8 +1610,8 @@ BOOL ClearAllBreakpoints()
//**************************************************************************************
{
CONTEXT Context;
- PTHREADBREAKPOINTS CurrentThreadBreakpoint;
- unsigned int Register;
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint;
+ unsigned int Register;
CurrentThreadBreakpoint = MainThreadBreakpointList;
@@ -1609,7 +1642,7 @@ BOOL ClearAllBreakpoints()
if (!GetThreadContext(CurrentThreadBreakpoint->ThreadHandle, &Context))
{
- DoOutputDebugString("ClearAllBreakpoints: Error getting thread context (thread %d).\n", CurrentThreadBreakpoint->ThreadId);
+ DoOutputDebugString("ClearAllBreakpoints: Error getting thread context (thread %d, handle 0x%x).\n", CurrentThreadBreakpoint->ThreadId, CurrentThreadBreakpoint->ThreadHandle);
return FALSE;
}
@@ -1619,16 +1652,16 @@ BOOL ClearAllBreakpoints()
Context.Dr3 = 0;
Context.Dr6 = 0;
Context.Dr7 = 0;
-
+
if (!SetThreadContext(CurrentThreadBreakpoint->ThreadHandle, &Context))
{
DoOutputDebugString("ClearAllBreakpoints: Error setting thread context (thread %d).\n", CurrentThreadBreakpoint->ThreadId);
return FALSE;
}
-
+
CurrentThreadBreakpoint = CurrentThreadBreakpoint->NextThreadBreakpoints;
}
-
+
return TRUE;
}
@@ -1641,52 +1674,52 @@ BOOL ContextClearBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpointInfo)
if (Context == NULL)
return FALSE;
-
+
Dr0 = &(Context->Dr0);
Dr1 = &(Context->Dr1);
Dr2 = &(Context->Dr2);
Dr3 = &(Context->Dr3);
Dr7 = (PDR7)&(Context->Dr7);
-
+
DoOutputDebugString("ContextClearBreakpoint: Clearing breakpoint %i\n", pBreakpointInfo->Register);
-
+
if (pBreakpointInfo->Register == 0)
{
*Dr0 = 0;
Dr7->LEN0 = 0;
Dr7->RWE0 = 0;
- Dr7->L0 = 0;
+ Dr7->L0 = 0;
}
else if (pBreakpointInfo->Register == 1)
{
*Dr1 = 0;
Dr7->LEN1 = 0;
Dr7->RWE1 = 0;
- Dr7->L1 = 0;
+ Dr7->L1 = 0;
}
else if (pBreakpointInfo->Register == 2)
{
*Dr2 = 0;
Dr7->LEN2 = 0;
Dr7->RWE2 = 0;
- Dr7->L2 = 0;
+ Dr7->L2 = 0;
}
else if (pBreakpointInfo->Register == 3)
{
*Dr3 = 0;
Dr7->LEN3 = 0;
Dr7->RWE3 = 0;
- Dr7->L3 = 0;
+ Dr7->L3 = 0;
}
#ifndef _WIN64
if (pBreakpointInfo->Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
WoW64UnpatchBreakpoint(pBreakpointInfo->Register);
-#endif
-
+#endif
+
Context->Dr6 = 0;
-
-#ifdef _WIN64
+
+#ifdef _WIN64
if (pBreakpointInfo->ThreadHandle == NULL)
{
DoOutputDebugString("ContextClearBreakpoint: No thread handle found in breakpoints found for current thread %d.\n", GetCurrentThreadId());
@@ -1694,16 +1727,16 @@ BOOL ContextClearBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpointInfo)
}
Context->ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
+
if (!SetThreadContext(pBreakpointInfo->ThreadHandle, Context))
{
DoOutputErrorString("ContextClearBreakpoint: SetThreadContext failed");
return FALSE;
- }
+ }
else
DoOutputDebugString("ContextClearBreakpoint: SetThreadContext success.\n");
#endif
-
+
pBreakpointInfo->Address = 0;
pBreakpointInfo->Size = 0;
pBreakpointInfo->Callback = 0;
@@ -1717,8 +1750,8 @@ BOOL ClearBreakpointsInRange(DWORD ThreadId, PVOID BaseAddress, SIZE_T Size)
//**************************************************************************************
{
unsigned int Register;
- DWORD CurrentThreadId;
-
+ DWORD CurrentThreadId;
+
PTHREADBREAKPOINTS CurrentThreadBreakpoint = MainThreadBreakpointList;
if (BaseAddress == NULL)
@@ -1726,15 +1759,15 @@ BOOL ClearBreakpointsInRange(DWORD ThreadId, PVOID BaseAddress, SIZE_T Size)
DoOutputDebugString("ClearBreakpointsInRange: No address supplied (may have already been cleared).\n");
return FALSE;
}
-
+
if (Size == 0)
{
DoOutputDebugString("ClearBreakpointsInRange: Size supplied is zero.\n");
return FALSE;
}
-
+
DoOutputDebugString("ClearBreakpointsInRange: Clearing breakpoints in range 0x%x - 0x%x.\n", BaseAddress, (BYTE*)BaseAddress + Size);
-
+
while (CurrentThreadBreakpoint)
{
CurrentThreadId = MyGetThreadId(CurrentThreadBreakpoint->ThreadHandle);
@@ -1743,20 +1776,20 @@ BOOL ClearBreakpointsInRange(DWORD ThreadId, PVOID BaseAddress, SIZE_T Size)
{
for (Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
{
- if ((DWORD_PTR)CurrentThreadBreakpoint->BreakpointInfo[Register].Address >= (DWORD_PTR)BaseAddress
+ if ((DWORD_PTR)CurrentThreadBreakpoint->BreakpointInfo[Register].Address >= (DWORD_PTR)BaseAddress
&& (DWORD_PTR)CurrentThreadBreakpoint->BreakpointInfo[Register].Address < (DWORD_PTR)((BYTE*)BaseAddress + Size))
{
DoOutputDebugString("ClearBreakpointsInRange: Clearing breakpoint %d address 0x%x.\n", Register, CurrentThreadBreakpoint->BreakpointInfo[Register].Address);
ClearBreakpoint(CurrentThreadBreakpoint->ThreadId, Register);
}
}
-
+
return TRUE;
}
else
CurrentThreadBreakpoint = CurrentThreadBreakpoint->NextThreadBreakpoints;
}
-
+
return FALSE;
}
@@ -1766,9 +1799,9 @@ BOOL SetResumeFlag(PCONTEXT Context)
{
if (Context == NULL)
return FALSE;
-
+
Context->EFlags |= FL_RF;
-
+
return TRUE;
}
@@ -1778,9 +1811,69 @@ BOOL SetZeroFlag(PCONTEXT Context)
{
if (Context == NULL)
return FALSE;
-
+
Context->EFlags |= FL_ZF;
-
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL ClearZeroFlag(PCONTEXT Context)
+//**************************************************************************************
+{
+ if (Context == NULL)
+ return FALSE;
+
+ Context->EFlags &= ~FL_ZF;
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL FlipZeroFlag(PCONTEXT Context)
+//**************************************************************************************
+{
+ if (Context == NULL)
+ return FALSE;
+
+ Context->EFlags ^= FL_ZF;
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL SetSignFlag(PCONTEXT Context)
+//**************************************************************************************
+{
+ if (Context == NULL)
+ return FALSE;
+
+ Context->EFlags |= FL_SF;
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL ClearSignFlag(PCONTEXT Context)
+//**************************************************************************************
+{
+ if (Context == NULL)
+ return FALSE;
+
+ Context->EFlags &= ~FL_SF;
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL FlipSignFlag(PCONTEXT Context)
+//**************************************************************************************
+{
+ if (Context == NULL)
+ return FALSE;
+
+ Context->EFlags ^= FL_SF;
+
return TRUE;
}
@@ -1788,12 +1881,18 @@ BOOL SetZeroFlag(PCONTEXT Context)
BOOL SetSingleStepMode(PCONTEXT Context, PVOID Handler)
//**************************************************************************************
{
- if (Context == NULL)
+ if (Context == NULL)
return FALSE;
-
+
// set the trap flag
Context->EFlags |= FL_TF;
-
+
+#ifdef BRANCH_TRACE
+ // set bits 8 & 9, LBR & BTF bits for branch trace
+ PDR7 Dr7 = (PDR7)&(Context->Dr7);
+ //Dr7->LE = 1;
+ Dr7->GE = 1;
+#endif
SingleStepHandler = (SINGLE_STEP_HANDLER)Handler;
return TRUE;
@@ -1810,9 +1909,9 @@ BOOL ClearSingleStepMode(PCONTEXT Context)
Context->EFlags &= ~FL_TF;
TrapIndex = 0;
-
+
SingleStepHandler = NULL;
-
+
return TRUE;
}
@@ -1820,7 +1919,7 @@ BOOL ClearSingleStepMode(PCONTEXT Context)
BOOL StepOverExecutionBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpointInfo)
//**************************************************************************************
// This function allows us to get past an execution breakpoint while leaving it set. It
-// diaables the breakpoint, sets single-step mode to step over the instruction, whereupon
+// diaables the breakpoint, sets single-step mode to step over the instruction, whereupon
// the breakpoint is restored in ResumeAfterExecutionBreakpoint and execution resumed.
{
PDR7 Dr7;
@@ -1829,7 +1928,7 @@ BOOL StepOverExecutionBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpointIn
return FALSE;
Dr7 = (PDR7)&(Context->Dr7);
-
+
switch(pBreakpointInfo->Register)
{
case 0:
@@ -1848,12 +1947,12 @@ BOOL StepOverExecutionBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpointIn
// set the trap flag
Context->EFlags |= FL_TF;
-
+
// set the 'trap index' so we know which 'register' we're skipping
// (off by one to allow 'set'/'unset' to be signified by !0/0)
TrapIndex = pBreakpointInfo->Register + 1;
-#ifdef _WIN64
+#ifdef _WIN64
if (pBreakpointInfo->ThreadHandle == NULL)
{
DoOutputDebugString("StepOverExecutionBreakpoint: No thread handle found in breakpoints found for current thread %d.\n", GetCurrentThreadId());
@@ -1861,14 +1960,14 @@ BOOL StepOverExecutionBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpointIn
}
Context->ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
+
if (!SetThreadContext(pBreakpointInfo->ThreadHandle, Context))
{
DoOutputErrorString("StepOverExecutionBreakpoint: SetThreadContext failed");
return FALSE;
- }
+ }
#endif
-
+
return TRUE;
}
@@ -1882,15 +1981,15 @@ BOOL ResumeAfterExecutionBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpoin
return FALSE;
Dr7 = (PDR7)&(Context->Dr7);
-
-#ifdef _WIN64
+
+#ifdef _WIN64
if (!pBreakpointInfo)
{
DoOutputDebugString("ResumeAfterExecutionBreakpoint: pBreakpointInfo NULL.\n");
return FALSE;
- }
+ }
#endif
-
+
switch(TrapIndex-1)
{
case 0:
@@ -1909,8 +2008,8 @@ BOOL ResumeAfterExecutionBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpoin
// Clear the trap flag
Context->EFlags &= ~FL_TF;
-
-#ifdef _WIN64
+
+#ifdef _WIN64
if (pBreakpointInfo->ThreadHandle == NULL)
{
DoOutputDebugString("ResumeAfterExecutionBreakpoint: No thread handle found in breakpoints found for current thread %d.\n", GetCurrentThreadId());
@@ -1918,17 +2017,17 @@ BOOL ResumeAfterExecutionBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpoin
}
Context->ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
+
if (!SetThreadContext(pBreakpointInfo->ThreadHandle, Context))
{
DoOutputErrorString("ResumeAfterExecutionBreakpoint: SetThreadContext failed");
return FALSE;
}
#endif
-
+
// clear the 'trap index'
TrapIndex = 0;
-
+
return TRUE;
}
@@ -1949,7 +2048,7 @@ BOOL ClearDebugRegister
PDWORD_PTR Dr2 = &Context.Dr2;
PDWORD_PTR Dr3 = &Context.Dr3;
PDR7 Dr7 = (PDR7)&(Context.Dr7);
-
+
if ((unsigned int)Type > 3)
{
DoOutputDebugString("ClearDebugRegister: %d is an invalid breakpoint type, must be 0-3.\n", Type);
@@ -1961,7 +2060,7 @@ BOOL ClearDebugRegister
DoOutputDebugString("ClearDebugRegister: %d is an invalid register, must be 0-3.\n", Register);
return FALSE;
}
-
+
if (Size < 0 || Size > 8)
{
DoOutputDebugString("ClearDebugRegister: %d is an invalid Size, must be 1, 2, 4 or 8.\n", Size);
@@ -1969,60 +2068,60 @@ BOOL ClearDebugRegister
}
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
+
if (!GetThreadContext(hThread, &Context))
{
DoOutputDebugString("ClearDebugRegister: Initial GetThreadContext failed");
return FALSE;
- }
+ }
if (Register == 0)
{
*Dr0 = 0;
Dr7->LEN0 = 0;
Dr7->RWE0 = 0;
- Dr7->L0 = 0;
+ Dr7->L0 = 0;
}
else if (Register == 1)
{
*Dr1 = 0;
Dr7->LEN1 = 0;
Dr7->RWE1 = 0;
- Dr7->L1 = 0;
+ Dr7->L1 = 0;
}
else if (Register == 2)
{
*Dr2 = 0;
Dr7->LEN2 = 0;
Dr7->RWE2 = 0;
- Dr7->L2 = 0;
+ Dr7->L2 = 0;
}
else if (Register == 3)
{
*Dr3 = 0;
Dr7->LEN3 = 0;
Dr7->RWE3 = 0;
- Dr7->L3 = 0;
+ Dr7->L3 = 0;
}
#ifndef _WIN64
if (Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)Address))
WoW64UnpatchBreakpoint(Register);
-#endif
-
+#endif
+
Context.Dr6 = 0;
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
+
if (!SetThreadContext(hThread, &Context))
{
DoOutputDebugString("ClearDebugRegister: SetThreadContext failed");
return FALSE;
- }
-
+ }
+
if (DoCloseHandle == TRUE)
CloseHandle(hThread);
-
+
return TRUE;
}
@@ -2031,7 +2130,7 @@ int ContextCheckDebugRegister(CONTEXT Context, int Register)
//**************************************************************************************
{
PDR7 Dr7;
-
+
if (Register < 0 || Register > 3)
{
DoOutputDebugString("ContextCheckDebugRegister: %d is an invalid register, must be 0-3.\n", Register);
@@ -2048,7 +2147,7 @@ int ContextCheckDebugRegister(CONTEXT Context, int Register)
return Dr7->L2;
else if (Register == 3)
return Dr7->L3;
-
+
// should not happen
return -1;
}
@@ -2059,7 +2158,7 @@ int CheckDebugRegister(HANDLE hThread, int Register)
{
CONTEXT Context;
PDR7 Dr7;
-
+
if (Register < 0 || Register > 3)
{
DoOutputDebugString("CheckDebugRegister: %d is an invalid register, must be 0-3.\n", Register);
@@ -2067,9 +2166,9 @@ int CheckDebugRegister(HANDLE hThread, int Register)
}
Dr7 = (PDR7)&(Context.Dr7);
-
+
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
+
if (!GetThreadContext(hThread, &Context))
{
DoOutputDebugString("CheckDebugRegister: GetThreadContext failed - FATAL\n");
@@ -2084,7 +2183,7 @@ int CheckDebugRegister(HANDLE hThread, int Register)
return Dr7->L2;
else if (Register == 3)
return Dr7->L3;
-
+
// should not happen
return -1;
}
@@ -2095,19 +2194,19 @@ BOOL ContextSetBreakpoint(PTHREADBREAKPOINTS ReferenceThreadBreakpoint)
//**************************************************************************************
{
PTHREADBREAKPOINTS CurrentThreadBreakpoint;
-
+
if (ReferenceThreadBreakpoint == NULL)
{
DoOutputDebugString("ContextSetBreakpoint: ReferenceThreadBreakpoint NULL.\n");
- return FALSE;
+ return FALSE;
}
-
+
if (MainThreadBreakpointList == NULL)
{
DoOutputDebugString("ContextSetBreakpoint: MainThreadBreakpointList NULL.\n");
- return FALSE;
+ return FALSE;
}
-
+
CurrentThreadBreakpoint = MainThreadBreakpointList;
while (CurrentThreadBreakpoint)
@@ -2123,21 +2222,21 @@ BOOL ContextSetBreakpoint(PTHREADBREAKPOINTS ReferenceThreadBreakpoint)
CurrentThreadBreakpoint->BreakpointInfo[i].Address = ReferenceThreadBreakpoint->BreakpointInfo[i].Address;
CurrentThreadBreakpoint->BreakpointInfo[i].Type = ReferenceThreadBreakpoint->BreakpointInfo[i].Type;
CurrentThreadBreakpoint->BreakpointInfo[i].Callback = ReferenceThreadBreakpoint->BreakpointInfo[i].Callback;
-
+
if (CurrentThreadBreakpoint->BreakpointInfo[i].Address)
SetThreadBreakpoint(CurrentThreadBreakpoint->ThreadId, CurrentThreadBreakpoint->BreakpointInfo[i].Register, CurrentThreadBreakpoint->BreakpointInfo[i].Size, CurrentThreadBreakpoint->BreakpointInfo[i].Address, CurrentThreadBreakpoint->BreakpointInfo[i].Type, CurrentThreadBreakpoint->BreakpointInfo[i].Callback);
}
}
-
+
CurrentThreadBreakpoint = CurrentThreadBreakpoint->NextThreadBreakpoints;
}
-
+
return TRUE;
}
//**************************************************************************************
-BOOL ContextSetThreadBreakpoint
+BOOL ContextSetThreadBreakpointEx
//**************************************************************************************
(
PCONTEXT Context,
@@ -2145,33 +2244,32 @@ BOOL ContextSetThreadBreakpoint
int Size,
LPVOID Address,
DWORD Type,
- PVOID Callback
+ PVOID Callback,
+ BOOL NoSetThreadContext
)
{
PTHREADBREAKPOINTS CurrentThreadBreakpoint;
-
+
if (Register > 3 || Register < 0)
{
DoOutputDebugString("ContextSetThreadBreakpoint: Error - register value %d, can only have value 0-3.\n", Register);
return FALSE;
}
-
- if (!ContextSetDebugRegister(Context, Register, Size, Address, Type))
+
+ if (!ContextSetDebugRegisterEx(Context, Register, Size, Address, Type, NoSetThreadContext))
{
DoOutputDebugString("ContextSetThreadBreakpoint: Call to ContextSetDebugRegister failed.\n");
}
else
{
- DoOutputDebugString("ContextSetThreadBreakpoint: Call to ContextSetDebugRegister succeeded.\n");
-
CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("ContextSetThreadBreakpoint: Error - Failed to acquire thread breakpoints.\n");
return FALSE;
}
-
+
CurrentThreadBreakpoint->BreakpointInfo[Register].ThreadHandle = CurrentThreadBreakpoint->ThreadHandle;
CurrentThreadBreakpoint->BreakpointInfo[Register].Register = Register;
CurrentThreadBreakpoint->BreakpointInfo[Register].Size = Size;
@@ -2180,31 +2278,25 @@ BOOL ContextSetThreadBreakpoint
CurrentThreadBreakpoint->BreakpointInfo[Register].Callback = Callback;
}
-#ifdef _WIN64
- if (CurrentThreadBreakpoint->ThreadHandle == NULL)
- {
- DoOutputDebugString("ContextSetThreadBreakpoint: No thread handle found in breakpoints found for current thread %d.\n", GetCurrentThreadId());
- return FALSE;
- }
-
- Context->ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
- if (!SetThreadContext(CurrentThreadBreakpoint->ThreadHandle, Context))
- {
- DoOutputErrorString("ContextSetThreadBreakpoint: SetThreadContext failed");
- return FALSE;
- }
-#endif
-
- //if (!ContextSetBreakpoint(CurrentThreadBreakpoint))
- //{
- // DoOutputErrorString("ContextSetThreadBreakpoint: ContextSetBreakpoint failed");
- // return FALSE;
- //}
return TRUE;
}
+//**************************************************************************************
+BOOL ContextSetThreadBreakpoint
+//**************************************************************************************
+(
+ PCONTEXT Context,
+ int Register,
+ int Size,
+ LPVOID Address,
+ DWORD Type,
+ PVOID Callback
+)
+{
+ return ContextSetThreadBreakpointEx(Context, Register, Size, Address, Type, Callback, FALSE);
+}
+
//**************************************************************************************
BOOL ContextSetNextAvailableBreakpoint
//**************************************************************************************
@@ -2230,7 +2322,7 @@ BOOL ContextSetNextAvailableBreakpoint
else
{
unsigned int TempRegister;
-
+
if (!ContextGetNextAvailableBreakpoint(Context, &TempRegister))
{
DoOutputDebugString("ContextSetNextAvailableBreakpoint: ContextGetNextAvailableBreakpoint failed\n");
@@ -2255,9 +2347,9 @@ BOOL ContextUpdateCurrentBreakpoint
PTHREADBREAKPOINTS CurrentThreadBreakpoint;
PBREAKPOINTINFO pBreakpointInfo;
unsigned int bp;
-
+
CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("ContextUpdateCurrentBreakpoint: Error - Failed to acquire thread breakpoints.\n");
@@ -2269,38 +2361,38 @@ BOOL ContextUpdateCurrentBreakpoint
if (Context->Dr6 & (DWORD_PTR)(1 << bp))
{
pBreakpointInfo = &(CurrentThreadBreakpoint->BreakpointInfo[bp]);
-
+
if (pBreakpointInfo == NULL)
{
DoOutputDebugString("ContextUpdateCurrentBreakpoint: Can't get BreakpointInfo.\n");
return FALSE;
- }
-
- if (pBreakpointInfo->Register == bp)
+ }
+
+ if (pBreakpointInfo->Register == bp)
{
if (bp == 0 && ((DWORD_PTR)pBreakpointInfo->Address == Context->Dr0) && ((DWORD)pBreakpointInfo->Type == ((PDR7)&(Context->Dr7))->RWE0))
{
- return ContextSetThreadBreakpoint(Context, 0, Size, Address, Type, Callback);
- }
+ return ContextSetThreadBreakpoint(Context, 0, Size, Address, Type, Callback);
+ }
if (bp == 1 && ((DWORD_PTR)pBreakpointInfo->Address == Context->Dr1) && ((DWORD)pBreakpointInfo->Type == ((PDR7)&(Context->Dr7))->RWE1))
{
- return ContextSetThreadBreakpoint(Context, 1, Size, Address, Type, Callback);
- }
+ return ContextSetThreadBreakpoint(Context, 1, Size, Address, Type, Callback);
+ }
if (bp == 2 && ((DWORD_PTR)pBreakpointInfo->Address == Context->Dr2) && ((DWORD)pBreakpointInfo->Type == ((PDR7)&(Context->Dr7))->RWE2))
{
- return ContextSetThreadBreakpoint(Context, 2, Size, Address, Type, Callback);
- }
+ return ContextSetThreadBreakpoint(Context, 2, Size, Address, Type, Callback);
+ }
if (bp == 3 && ((DWORD_PTR)pBreakpointInfo->Address == Context->Dr3) && ((DWORD)pBreakpointInfo->Type == ((PDR7)&(Context->Dr7))->RWE3))
{
- return ContextSetThreadBreakpoint(Context, 3, Size, Address, Type, Callback);
- }
+ return ContextSetThreadBreakpoint(Context, 3, Size, Address, Type, Callback);
+ }
}
}
}
-
+
return FALSE;
}
@@ -2314,9 +2406,9 @@ BOOL ContextClearCurrentBreakpoint
PTHREADBREAKPOINTS CurrentThreadBreakpoint;
PBREAKPOINTINFO pBreakpointInfo;
unsigned int bp;
-
+
CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("ContextUpdateCurrentBreakpoint: Error - Failed to acquire thread breakpoints.\n");
@@ -2328,37 +2420,69 @@ BOOL ContextClearCurrentBreakpoint
if (Context->Dr6 & (DWORD_PTR)(1 << bp))
{
pBreakpointInfo = &(CurrentThreadBreakpoint->BreakpointInfo[bp]);
-
+
if (pBreakpointInfo == NULL)
{
DoOutputDebugString("ContextUpdateCurrentBreakpoint: Can't get BreakpointInfo.\n");
return FALSE;
- }
+ }
if (pBreakpointInfo->Register == bp)
- return ContextClearBreakpoint(Context, pBreakpointInfo);
+ return ContextClearBreakpoint(Context, pBreakpointInfo);
}
}
-
+
return FALSE;
}
//**************************************************************************************
-DWORD WINAPI SetBreakpointThread(LPVOID lpParam)
+BOOL ContextSetThreadBreakpointsEx(PCONTEXT ThreadContext, PTHREADBREAKPOINTS ThreadBreakpoints, BOOL NoSetThreadContext)
//**************************************************************************************
-{
+{
+ if (!ThreadContext)
+ return FALSE;
+
+ for (unsigned int Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
+ {
+ if (!ContextSetThreadBreakpointEx
+ (
+ ThreadContext,
+ ThreadBreakpoints->BreakpointInfo[Register].Register,
+ ThreadBreakpoints->BreakpointInfo[Register].Size,
+ ThreadBreakpoints->BreakpointInfo[Register].Address,
+ ThreadBreakpoints->BreakpointInfo[Register].Type,
+ ThreadBreakpoints->BreakpointInfo[Register].Callback,
+ NoSetThreadContext
+ ))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL ContextSetThreadBreakpoints(PCONTEXT ThreadContext, PTHREADBREAKPOINTS ThreadBreakpoints)
+//**************************************************************************************
+{
+ return ContextSetThreadBreakpointsEx(ThreadContext, ThreadBreakpoints, FALSE);
+}
+
+//**************************************************************************************
+DWORD WINAPI SetBreakpointThread(LPVOID lpParam)
+//**************************************************************************************
+{
DWORD RetVal;
-
+
PBREAKPOINTINFO pBreakpointInfo = (PBREAKPOINTINFO)lpParam;
-
+
if (SuspendThread(pBreakpointInfo->ThreadHandle) == 0xFFFFFFFF)
DoOutputErrorString("SetBreakpointThread: Call to SuspendThread failed for thread handle 0x%x", pBreakpointInfo->ThreadHandle);
-
+
if (!SetDebugRegister(pBreakpointInfo->ThreadHandle, pBreakpointInfo->Register, pBreakpointInfo->Size, pBreakpointInfo->Address, pBreakpointInfo->Type))
DoOutputErrorString("SetBreakpointThread: Call to SetDebugRegister failed for thread handle 0x%x", pBreakpointInfo->ThreadHandle);
RetVal = ResumeThread(pBreakpointInfo->ThreadHandle);
-
+
if (RetVal == -1)
DoOutputErrorString("SetBreakpointThread: ResumeThread failed for thread handle 0x%x", pBreakpointInfo->ThreadHandle);
else if (RetVal == 0)
@@ -2366,19 +2490,19 @@ DWORD WINAPI SetBreakpointThread(LPVOID lpParam)
else if (g_config.debug)
DoOutputDebugString("SetBreakpointThread: Sample thread with handle 0x%x was suspended, now resumed.\n", pBreakpointInfo->ThreadHandle);
- return 1;
-}
+ return 1;
+}
//**************************************************************************************
-DWORD WINAPI ClearBreakpointThread(LPVOID lpParam)
+DWORD WINAPI ClearBreakpointThread(LPVOID lpParam)
//**************************************************************************************
-{
+{
DWORD RetVal;
PBREAKPOINTINFO pBreakpointInfo = (PBREAKPOINTINFO)lpParam;
-
+
if (SuspendThread(pBreakpointInfo->ThreadHandle) == 0xFFFFFFFF)
DoOutputErrorString("ClearBreakpointThread: Call to SuspendThread failed");
-
+
if (!ClearDebugRegister(pBreakpointInfo->ThreadHandle, pBreakpointInfo->Register, pBreakpointInfo->Size, pBreakpointInfo->Address, pBreakpointInfo->Type))
{
DoOutputDebugString("ClearBreakpointThread: Call to ClearDebugRegister failed.\n");
@@ -2398,58 +2522,8 @@ DWORD WINAPI ClearBreakpointThread(LPVOID lpParam)
DoOutputDebugString("ClearBreakpointThread: Sample thread was suspended, now resumed.\n");
}
- DebugOutputThreadBreakpoints();
-
- return TRUE;
-}
-
-//**************************************************************************************
-BOOL ClearBreakpointWithoutThread(DWORD ThreadId, int Register)
-//**************************************************************************************
-{
- PBREAKPOINTINFO pBreakpointInfo;
- PTHREADBREAKPOINTS CurrentThreadBreakpoint;
-
- if (Register > 3 || Register < 0)
- {
- DoOutputDebugString("ClearBreakpointWithoutThread: Error - register value %d, can only have value 0-3.\n", Register);
- return FALSE;
- }
-
- CurrentThreadBreakpoint = GetThreadBreakpoints(ThreadId);
-
- if (CurrentThreadBreakpoint == NULL)
- {
- DoOutputDebugString("ClearBreakpointWithoutThread: Creating new thread breakpoints for thread %d.\n", ThreadId);
- CurrentThreadBreakpoint = CreateThreadBreakpoints(ThreadId);
- }
-
- if (CurrentThreadBreakpoint == NULL)
- {
- DoOutputDebugString("ClearBreakpointWithoutThread: Cannot create new thread breakpoints - FATAL.\n");
- return FALSE;
- }
-
- pBreakpointInfo = &CurrentThreadBreakpoint->BreakpointInfo[Register];
-
- if (CurrentThreadBreakpoint->ThreadHandle == NULL)
- {
- DoOutputDebugString("ClearBreakpointWithoutThread: There is no thread handle in the thread breakpoint - Error.\n");
- return FALSE;
- }
+ DebugOutputThreadBreakpoints();
- if (!ClearDebugRegister(pBreakpointInfo->ThreadHandle, pBreakpointInfo->Register, pBreakpointInfo->Size, pBreakpointInfo->Address, pBreakpointInfo->Type))
- {
- DoOutputDebugString("ClearBreakpointWithoutThread: Call to ClearDebugRegister failed.\n");
- return FALSE;
- }
-
- //pBreakpointInfo->Register = 0;
- pBreakpointInfo->Size = 0;
- pBreakpointInfo->Address = 0;
- pBreakpointInfo->Type = 0;
- pBreakpointInfo->Callback = NULL;
-
return TRUE;
}
@@ -2473,16 +2547,16 @@ BOOL SetBreakpointWithoutThread
{
DoOutputDebugString("SetBreakpointWithoutThread: Error - register value %d, can only have value 0-3.\n", Register);
return FALSE;
- }
-
+ }
+
CurrentThreadBreakpoint = GetThreadBreakpoints(ThreadId);
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("SetBreakpointWithoutThread: Creating new thread breakpoints for thread %d.\n", ThreadId);
CurrentThreadBreakpoint = CreateThreadBreakpoints(ThreadId);
}
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("SetBreakpointWithoutThread: Cannot create new thread breakpoints - FATAL.\n");
@@ -2490,34 +2564,34 @@ BOOL SetBreakpointWithoutThread
}
pBreakpointInfo = &CurrentThreadBreakpoint->BreakpointInfo[Register];
-
+
if (CurrentThreadBreakpoint->ThreadHandle == NULL)
{
DoOutputDebugString("SetBreakpointWithoutThread: There is no thread handle in the thread breakpoint - Error.\n");
return FALSE;
}
-
+
pBreakpointInfo->ThreadHandle = CurrentThreadBreakpoint->ThreadHandle;
pBreakpointInfo->Register = Register;
pBreakpointInfo->Size = Size;
pBreakpointInfo->Address = Address;
pBreakpointInfo->Type = Type;
pBreakpointInfo->Callback = Callback;
-
+
__try
{
RetVal = SetDebugRegister(pBreakpointInfo->ThreadHandle, Register, Size, Address, Type);
}
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
DoOutputErrorString("SetBreakpointWithoutThread: Exception calling SetDebugRegister");
return FALSE;
}
-
+
// Debug
DoOutputDebugString("SetBreakpointWithoutThread: bp set with register %d\n", Register);
- return TRUE;
+ return TRUE;
}
//**************************************************************************************
@@ -2540,13 +2614,13 @@ BOOL SetThreadBreakpoint
HANDLE hSetBreakpointThread;
DWORD SetBreakpointThreadId;
BOOL RetVal;
-
+
if (Register > 3 || Register < 0)
{
DoOutputDebugString("SetThreadBreakpoint: Error - register value %d, can only have value 0-3.\n", Register);
return FALSE;
- }
-
+ }
+
CurrentThreadBreakpoint = GetThreadBreakpoints(ThreadId);
if (CurrentThreadBreakpoint == NULL)
@@ -2554,7 +2628,7 @@ BOOL SetThreadBreakpoint
DoOutputDebugString("SetThreadBreakpoint: Creating new thread breakpoints for thread %d.\n", ThreadId);
CurrentThreadBreakpoint = CreateThreadBreakpoints(ThreadId);
}
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("SetThreadBreakpoint: Cannot create new thread breakpoints - error.\n");
@@ -2562,13 +2636,13 @@ BOOL SetThreadBreakpoint
}
pBreakpointInfo = &CurrentThreadBreakpoint->BreakpointInfo[Register];
-
+
if (CurrentThreadBreakpoint->ThreadHandle == NULL)
{
DoOutputDebugString("SetThreadBreakpoint: There is no thread handle in the thread breakpoint - Error.\n");
return FALSE;
}
-
+
pBreakpointInfo->ThreadHandle = CurrentThreadBreakpoint->ThreadHandle;
pBreakpointInfo->Register = Register;
pBreakpointInfo->Size = Size;
@@ -2577,21 +2651,13 @@ BOOL SetThreadBreakpoint
pBreakpointInfo->Callback = Callback;
if (VECTORED_HANDLER)
- {
CAPEExceptionFilterHandle = AddVectoredExceptionHandler(1, CAPEExceptionFilter);
- OriginalExceptionHandler = NULL;
- }
- else
- {
- OriginalExceptionHandler = SetUnhandledExceptionFilter(CAPEExceptionFilter);
- CAPEExceptionFilterHandle = NULL;
- }
__try
{
- hSetBreakpointThread = CreateThread(NULL, 0, SetBreakpointThread, pBreakpointInfo, 0, &SetBreakpointThreadId);
+ hSetBreakpointThread = CreateThread(NULL, 0, SetBreakpointThread, pBreakpointInfo, 0, &SetBreakpointThreadId);
}
- __except(EXCEPTION_EXECUTE_HANDLER)
+ __except(EXCEPTION_EXECUTE_HANDLER)
{
DoOutputErrorString("SetThreadBreakpoint: An exception was raised creating SetBreakpointThread thread");
}
@@ -2599,29 +2665,29 @@ BOOL SetThreadBreakpoint
if (!hSetBreakpointThread)
{
DoOutputDebugString("SetThreadBreakpoint: Failed to create SetBreakpointThread thread, falling back to SetBreakpointWithoutThread.\n");
-
+
__try
{
RetVal = SetBreakpointWithoutThread(ThreadId, Register, Size, Address, Type, Callback);
}
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
DoOutputErrorString("SetThreadBreakpoint: Error calling SetBreakpointWithoutThread");
return FALSE;
}
-
+
return RetVal;
}
-
+
// We wait for the thread to complete - if this hasn't happened
// in under a second, we bail and set without creating a thread
RetVal = WaitForSingleObject(hSetBreakpointThread, 1000);
-
+
if (RetVal != WAIT_OBJECT_0)
{
TerminateThread(hSetBreakpointThread, 0);
DoOutputDebugString("SetThreadBreakpoint: SetBreakpointThread timeout, thread killed.\n");
-
+
RetVal = ResumeThread(CurrentThreadBreakpoint->ThreadHandle);
if (RetVal == -1)
{
@@ -2635,21 +2701,21 @@ BOOL SetThreadBreakpoint
{
DoOutputDebugString("SetThreadBreakpoint: Sample thread was suspended, now resumed. About to set breakpoint without thread.\n");
}
-
+
return SetBreakpointWithoutThread(ThreadId, Register, Size, Address, Type, Callback);
- }
-
- DoOutputDebugString("SetThreadBreakpoint: Set bp %d thread id %d type %d at address 0x%p, size %d with Callback 0x%x.\n",
- Register,
+ }
+
+ DoOutputDebugString("SetThreadBreakpoint: Set bp %d thread id %d type %d at address 0x%p, size %d with Callback 0x%x.\n",
+ Register,
ThreadId,
Type,
- Address,
- Size,
+ Address,
+ Size,
Callback
);
CloseHandle(hSetBreakpointThread);
-
+
return TRUE;
}
@@ -2667,9 +2733,9 @@ BOOL SetBreakpoint
if (MainThreadBreakpointList == NULL)
{
DoOutputDebugString("SetBreakpoint: MainThreadBreakpointList NULL.\n");
- return FALSE;
+ return FALSE;
}
-
+
PTHREADBREAKPOINTS ThreadBreakpoints = MainThreadBreakpointList;
while (ThreadBreakpoints)
@@ -2681,14 +2747,14 @@ BOOL SetBreakpoint
ThreadBreakpoints->BreakpointInfo[Register].Address = Address;
ThreadBreakpoints->BreakpointInfo[Register].Type = Type;
ThreadBreakpoints->BreakpointInfo[Register].Callback = Callback;
-
+
DoOutputDebugString("SetBreakpoint: About to call SetThreadBreakpoint for thread %d.\n", ThreadBreakpoints->ThreadId);
-
+
SetThreadBreakpoint(ThreadBreakpoints->ThreadId, Register, Size, Address, Type, Callback);
-
+
ThreadBreakpoints = ThreadBreakpoints->NextThreadBreakpoints;
}
-
+
return TRUE;
}
@@ -2699,7 +2765,7 @@ BOOL SetThreadBreakpoints(PTHREADBREAKPOINTS ThreadBreakpoints)
if (!ThreadBreakpoints->ThreadId)
{
DoOutputErrorString("SetThreadBreakpoints: Error - Thread ID missing from ThreadBreakpoints.\n");
- return FALSE;
+ return FALSE;
}
for (unsigned int Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
@@ -2712,10 +2778,10 @@ BOOL SetThreadBreakpoints(PTHREADBREAKPOINTS ThreadBreakpoints)
ThreadBreakpoints->BreakpointInfo[Register].Address,
ThreadBreakpoints->BreakpointInfo[Register].Type,
ThreadBreakpoints->BreakpointInfo[Register].Callback
- ))
+ ))
return FALSE;
}
-
+
return TRUE;
}
@@ -2723,91 +2789,50 @@ BOOL SetThreadBreakpoints(PTHREADBREAKPOINTS ThreadBreakpoints)
BOOL ClearBreakpoint(DWORD ThreadId, int Register)
//**************************************************************************************
{
- return ClearBreakpointWithoutThread(ThreadId, Register);
-/*
PBREAKPOINTINFO pBreakpointInfo;
PTHREADBREAKPOINTS CurrentThreadBreakpoint;
- HANDLE hClearBreakpointThread;
- BOOL RetVal;
if (Register > 3 || Register < 0)
{
DoOutputDebugString("ClearBreakpoint: Error - register value %d, can only have value 0-3.\n", Register);
return FALSE;
- }
-
- CurrentThreadBreakpoint = GetThreadBreakpoints(ThreadId);
-
+ }
+
+ CurrentThreadBreakpoint = GetThreadBreakpoints(ThreadId);
+
if (CurrentThreadBreakpoint == NULL)
{
- DoOutputDebugString("Cannot find thread breakpoints - failed to clear.\n");
+ DoOutputDebugString("ClearBreakpoint: Creating new thread breakpoints for thread %d.\n", ThreadId);
+ CurrentThreadBreakpoint = CreateThreadBreakpoints(ThreadId);
+ }
+
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("ClearBreakpoint: Cannot create new thread breakpoints - FATAL.\n");
return FALSE;
}
pBreakpointInfo = &CurrentThreadBreakpoint->BreakpointInfo[Register];
-
+
if (CurrentThreadBreakpoint->ThreadHandle == NULL)
{
DoOutputDebugString("ClearBreakpoint: There is no thread handle in the thread breakpoint - Error.\n");
return FALSE;
}
-
- pBreakpointInfo->ThreadHandle = CurrentThreadBreakpoint->ThreadHandle;
-
- __try
- {
- hClearBreakpointThread = CreateThread(NULL, 0, ClearBreakpointThread, pBreakpointInfo, 0, &ThreadId);
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- DoOutputErrorString("ClearBreakpoint: Unable to create ClearBreakpointThread thread");
- }
-
- if (hClearBreakpointThread)
- {
- DoOutputDebugString("ClearBreakpoint: thread created, handle 0x%x.\n", hClearBreakpointThread);
-
- // If this hasn't happened in under a second, we bail
- // and clear without creating a thread
- RetVal = WaitForSingleObject(hClearBreakpointThread, 1000);
- DoOutputDebugString("ClearBreakpoint: Aboot tae close handle.\n");
- //CloseHandle(hClearBreakpointThread);
-
- if (RetVal != WAIT_OBJECT_0)
- {
- DoOutputDebugString("ClearBreakpoint: thread timeout, falling back to clearing without thread.\n");
-
- return ClearBreakpointWithoutThread(ThreadId, Register);
- }
-
- DoOutputDebugString("ClearBreakpoint: Cleared breakpoint %d.\n", pBreakpointInfo->Register);
+ if (!ClearDebugRegister(pBreakpointInfo->ThreadHandle, pBreakpointInfo->Register, pBreakpointInfo->Size, pBreakpointInfo->Address, pBreakpointInfo->Type))
+ {
+ DoOutputDebugString("ClearBreakpoint: Call to ClearDebugRegister failed.\n");
+ return FALSE;
+ }
- return TRUE;
- }
- else
- {
- __try
- {
- RetVal = ClearBreakpointWithoutThread(ThreadId, Register);
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- DoOutputErrorString("ClearBreakpoint: Error calling ClearBreakpointWithoutThread");
- return FALSE;
- }
-
- return RetVal;
- }
-
//pBreakpointInfo->Register = 0;
pBreakpointInfo->Size = 0;
pBreakpointInfo->Address = 0;
pBreakpointInfo->Type = 0;
pBreakpointInfo->Callback = NULL;
-
+
return TRUE;
-*/
}
//**************************************************************************************
@@ -2829,7 +2854,7 @@ BOOL SetNextAvailableBreakpoint
DoOutputDebugString("SetNextAvailableBreakpoint: Creating new thread breakpoints for thread %d.\n", ThreadId);
CurrentThreadBreakpoint = CreateThreadBreakpoints(ThreadId);
}
-
+
if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("SetNextAvailableBreakpoint: Cannot create new thread breakpoints - FATAL.\n");
@@ -2864,64 +2889,56 @@ BOOL InitialiseDebugger(void)
if (MainThreadBreakpointList == NULL)
{
DoOutputDebugString("InitialiseDebugger: Failed to create thread breakpoints struct.\n");
- return FALSE;
+ return FALSE;
}
-
+
if (MainThreadBreakpointList->ThreadHandle == NULL)
{
DoOutputDebugString("InitialiseDebugger error: main thread handle not set.\n");
- return FALSE;
+ return FALSE;
}
-
+
// Initialise global variables
ChildProcessId = 0;
SingleStepHandler = NULL;
SampleVectoredHandler = NULL;
- VECTORED_HANDLER = TRUE;
+ VECTORED_HANDLER = FALSE;
#ifndef _WIN64
// Ensure wow64 patch is installed if needed
WoW64fix();
-#endif
+#endif
// Set up handler to catch breakpoint exceptions
if (VECTORED_HANDLER)
- {
CAPEExceptionFilterHandle = AddVectoredExceptionHandler(1, CAPEExceptionFilter);
- OriginalExceptionHandler = NULL;
- }
- else // deprecated alternative via unhandled exception filter
- {
- OriginalExceptionHandler = SetUnhandledExceptionFilter(CAPEExceptionFilter);
- CAPEExceptionFilterHandle = NULL;
- }
-
+
// Global switch for guard pages
GuardPagesDisabled = TRUE;
-
+
return TRUE;
}
//**************************************************************************************
DWORD_PTR GetNestedStackPointer(void)
//**************************************************************************************
-{
+{
CONTEXT context;
RtlCaptureContext(&context);
-
+
#ifdef _WIN64
return (DWORD_PTR)context.Rsp;
#else
return (DWORD_PTR)context.Esp;
-#endif
+#endif
}
#ifndef _WIN64
//**************************************************************************************
__declspec (naked dllexport) void DebuggerInit(void)
//**************************************************************************************
-{
+{
DWORD StackPointer;
_asm
@@ -2933,10 +2950,10 @@ __declspec (naked dllexport) void DebuggerInit(void)
sub esp, __LOCAL_SIZE
pushad
}
-
+
if (!InitialiseDebugger())
DoOutputDebugString("Debugger initialisation failure!\n");
-
+
// Package specific code
// End of package specific code
DoOutputDebugString("Debugger initialisation complete, about to execute OEP at 0x%p\n", OEP);
@@ -2954,16 +2971,16 @@ __declspec (naked dllexport) void DebuggerInit(void)
//**************************************************************************************
__declspec(dllexport) void DebuggerInit(void)
//**************************************************************************************
-{
+{
DWORD_PTR StackPointer;
StackPointer = GetNestedStackPointer() - 8; // this offset has been determined experimentally - TODO: tidy
-
+
if (!InitialiseDebugger())
DoOutputDebugString("Debugger initialisation failure!\n");
else
DoOutputDebugString("Debugger initialised, ESP = 0x%x\n", StackPointer);
-
+
// Package specific code
// End of package specific code
@@ -2975,36 +2992,36 @@ __declspec(dllexport) void DebuggerInit(void)
#endif
BOOL SendDebuggerMessage(PVOID Input)
-{
+{
BOOL fSuccess;
- DWORD cbReplyBytes, cbWritten;
+ DWORD cbReplyBytes, cbWritten;
cbReplyBytes = sizeof(PVOID);
-
+
if (hCapePipe == NULL)
- {
+ {
DoOutputErrorString("SendDebuggerMessage: hCapePipe NULL.");
return FALSE;
}
- // Write the reply to the pipe.
+ // Write the reply to the pipe.
fSuccess = WriteFile
- (
- hCapePipe, // handle to pipe
- &Input, // buffer to write from
- cbReplyBytes, // number of bytes to write
- &cbWritten, // number of bytes written
- NULL // not overlapped I/O
+ (
+ hCapePipe, // handle to pipe
+ &Input, // buffer to write from
+ cbReplyBytes, // number of bytes to write
+ &cbWritten, // number of bytes written
+ NULL // not overlapped I/O
);
if (!fSuccess || cbReplyBytes != cbWritten)
- {
+ {
DoOutputErrorString("SendDebuggerMessage: Failed to send message via pipe");
return FALSE;
}
DoOutputDebugString("SendDebuggerMessage: Sent message via pipe: 0x%x\n", Input);
-
+
return TRUE;
}
@@ -3012,14 +3029,14 @@ BOOL SendDebuggerMessage(PVOID Input)
BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD CreationFlags)
//**************************************************************************************
{
- HANDLE hProcess, hThread;
+ HANDLE hProcess, hThread;
char lpszPipename[MAX_PATH];
BOOL fSuccess, fConnected;
CONTEXT Context;
- DWORD cbBytesRead, cbWritten, cbReplyBytes;
+ DWORD cbBytesRead, cbWritten, cbReplyBytes;
memset(lpszPipename, 0, MAX_PATH*sizeof(CHAR));
-
+
sprintf_s(lpszPipename, MAX_PATH, "\\\\.\\pipe\\CAPEpipe_%x", ProcessId);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
@@ -3030,27 +3047,27 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
}
hThread = OpenThread(THREAD_ALL_ACCESS, TRUE, ThreadId);
- if (hThread == NULL)
+ if (hThread == NULL)
{
DoOutputErrorString("DebugNewProcess: OpenThread failed");
return FALSE;
}
hCapePipe = CreateNamedPipe
- (
- lpszPipename,
- PIPE_ACCESS_DUPLEX,
- PIPE_TYPE_MESSAGE |
- PIPE_READMODE_MESSAGE |
- PIPE_WAIT,
- PIPE_UNLIMITED_INSTANCES,
- PIPEBUFSIZE,
- PIPEBUFSIZE,
- 0,
+ (
+ lpszPipename,
+ PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_MESSAGE |
+ PIPE_READMODE_MESSAGE |
+ PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES,
+ PIPEBUFSIZE,
+ PIPEBUFSIZE,
+ 0,
NULL
- );
+ );
- if (hCapePipe == INVALID_HANDLE_VALUE)
+ if (hCapePipe == INVALID_HANDLE_VALUE)
{
DoOutputErrorString("DebugNewProcess: CreateNamedPipe failed");
return FALSE;
@@ -3059,11 +3076,11 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
DoOutputDebugString("DebugNewProcess: Announcing new process to Cuckoo, pid: %d\n", ProcessId);
pipe("DEBUGGER:%d,%d", ProcessId, ThreadId);
- fConnected = ConnectNamedPipe(hCapePipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+ fConnected = ConnectNamedPipe(hCapePipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
fSuccess = FALSE;
cbBytesRead = 0;
-
- if (!fConnected)
+
+ if (!fConnected)
{
DoOutputDebugString("DebugNewProcess: The client could not connect, closing pipe.\n");
CloseHandle(hCapePipe);
@@ -3071,18 +3088,18 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
}
DoOutputDebugString("DebugNewProcess: Client connected.\n");
-
+
fSuccess = ReadFile
- (
- hCapePipe,
- &DebuggerEP,
- sizeof(DWORD_PTR),
- &cbBytesRead,
- NULL
+ (
+ hCapePipe,
+ &DebuggerEP,
+ sizeof(DWORD_PTR),
+ &cbBytesRead,
+ NULL
);
-
+
if (!fSuccess || cbBytesRead == 0)
- {
+ {
if (GetLastError() == ERROR_BROKEN_PIPE)
{
DoOutputErrorString("DebugNewProcess: Client disconnected.");
@@ -3098,7 +3115,7 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
DoOutputErrorString("DebugNewProcess: Successfully read from pipe, however DebuggerEP = 0.");
return FALSE;
}
-
+
Context.ContextFlags = CONTEXT_ALL;
if (!GetThreadContext(hThread, &Context))
{
@@ -3110,22 +3127,22 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
OEP = (PVOID)Context.Rcx;
#else
OEP = (PVOID)Context.Eax;
-#endif
-
+#endif
+
cbWritten = 0;
cbReplyBytes = sizeof(DWORD_PTR);
- // Send the OEP to the new process
+ // Send the OEP to the new process
fSuccess = WriteFile
- (
- hCapePipe,
- &OEP,
+ (
+ hCapePipe,
+ &OEP,
cbReplyBytes,
- &cbWritten,
- NULL
+ &cbWritten,
+ NULL
);
if (!fSuccess || cbReplyBytes != cbWritten)
- {
+ {
DoOutputErrorString("DebugNewProcess: Failed to send OEP via pipe.");
return FALSE;
}
@@ -3133,13 +3150,13 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
DoOutputDebugString("DebugNewProcess: Sent OEP 0x%p via pipe\n", OEP);
Context.ContextFlags = CONTEXT_ALL;
-
+
#ifdef _WIN64
Context.Rcx = DebuggerEP; // set the new EP to debugger_init
#else
- Context.Eax = DebuggerEP;
-#endif
-
+ Context.Eax = DebuggerEP;
+#endif
+
if (!SetThreadContext(hThread, &Context))
{
DoOutputDebugString("DebugNewProcess: Failed to set new EP\n");
@@ -3151,7 +3168,7 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
#else
DoOutputDebugString("DebugNewProcess: Set new EP to DebuggerInit: 0x%x\n", Context.Eax);
#endif
-
+
CloseHandle(hProcess);
CloseHandle(hThread);
@@ -3161,99 +3178,99 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
//**************************************************************************************
DWORD WINAPI DebuggerLaunch(LPVOID lpParam)
//**************************************************************************************
-{
- HANDLE hPipe;
- BOOL fSuccess = FALSE, NT5;
+{
+ HANDLE hPipe;
+ BOOL fSuccess = FALSE, NT5;
DWORD cbRead, cbToWrite, cbWritten, dwMode;
PVOID FuncAddress;
- char lpszPipename[MAX_PATH];
+ char lpszPipename[MAX_PATH];
OSVERSIONINFO VersionInfo;
-
+
DoOutputDebugString("DebuggerLaunch: About to connect to CAPEpipe.\n");
memset(lpszPipename, 0, MAX_PATH*sizeof(CHAR));
-
+
sprintf_s(lpszPipename, MAX_PATH, "\\\\.\\pipe\\CAPEpipe_%x", GetCurrentProcessId());
-
- while (1)
- {
+
+ while (1)
+ {
hPipe = CreateFile(
- lpszPipename,
- GENERIC_READ |
- GENERIC_WRITE,
- 0,
- NULL,
- OPEN_EXISTING,
- 0,
- NULL);
-
- if (hPipe != INVALID_HANDLE_VALUE)
- break;
-
- if (GetLastError() != ERROR_PIPE_BUSY)
+ lpszPipename,
+ GENERIC_READ |
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+
+ if (hPipe != INVALID_HANDLE_VALUE)
+ break;
+
+ if (GetLastError() != ERROR_PIPE_BUSY)
{
- DoOutputErrorString("DebuggerLaunch: Could not open pipe");
+ DoOutputErrorString("DebuggerLaunch: Could not open pipe");
return -1;
}
- if (!WaitNamedPipe(lpszPipename, 20))
- {
- DoOutputDebugString("DebuggerLaunch: Could not open pipe: 20 ms wait timed out.\n");
+ if (!WaitNamedPipe(lpszPipename, 20))
+ {
+ DoOutputDebugString("DebuggerLaunch: Could not open pipe: 20 ms wait timed out.\n");
return -1;
- }
- }
+ }
+ }
- // The pipe connected; change to message-read mode.
- dwMode = PIPE_READMODE_MESSAGE;
+ // The pipe connected; change to message-read mode.
+ dwMode = PIPE_READMODE_MESSAGE;
fSuccess = SetNamedPipeHandleState
(
- hPipe,
+ hPipe,
&dwMode,
- NULL,
- NULL
+ NULL,
+ NULL
);
- if (!fSuccess)
+ if (!fSuccess)
{
- DoOutputDebugString("DebuggerLaunch: SetNamedPipeHandleState failed.\n");
+ DoOutputDebugString("DebuggerLaunch: SetNamedPipeHandleState failed.\n");
return -1;
}
// Send VA of DebuggerInit to loader
FuncAddress = &DebuggerInit;
-
+
cbToWrite = sizeof(PVOID);
-
+
fSuccess = WriteFile
(
- hPipe,
+ hPipe,
&FuncAddress,
- cbToWrite,
- &cbWritten,
- NULL
+ cbToWrite,
+ &cbWritten,
+ NULL
);
- if (!fSuccess)
+ if (!fSuccess)
{
- DoOutputErrorString("DebuggerLaunch: WriteFile to pipe failed");
+ DoOutputErrorString("DebuggerLaunch: WriteFile to pipe failed");
return -1;
}
DoOutputDebugString("DebuggerLaunch: DebuggerInit VA sent to loader: 0x%x\n", FuncAddress);
fSuccess = ReadFile(
- hPipe,
- &OEP,
- sizeof(DWORD_PTR),
+ hPipe,
+ &OEP,
+ sizeof(DWORD_PTR),
&cbRead,
- NULL);
-
+ NULL);
+
if (!fSuccess && GetLastError() == ERROR_MORE_DATA)
{
DoOutputDebugString("DebuggerLaunch: ReadFile on Pipe: ERROR_MORE_DATA\n");
CloseHandle(hPipe);
return -1;
}
-
+
if (!fSuccess)
{
DoOutputErrorString("DebuggerLaunch: ReadFile (OEP) from pipe failed");
@@ -3262,30 +3279,30 @@ DWORD WINAPI DebuggerLaunch(LPVOID lpParam)
}
DoOutputDebugString("DebuggerLaunch: Read OEP from pipe: 0x%p\n", OEP);
-
+
while (1)
{
fSuccess = ReadFile(
- hPipe,
- &OEP,
- sizeof(DWORD_PTR),
+ hPipe,
+ &OEP,
+ sizeof(DWORD_PTR),
&cbRead,
- NULL);
-
+ NULL);
+
if (!fSuccess && GetLastError() == ERROR_BROKEN_PIPE)
{
DoOutputDebugString("DebuggerLaunch: Pipe closed, no further updates to OEP\n");
CloseHandle(hPipe);
break;
}
-
+
if (!fSuccess && GetLastError() == ERROR_MORE_DATA)
{
DoOutputDebugString("DebuggerLaunch: ReadFile on Pipe: ERROR_MORE_DATA\n");
CloseHandle(hPipe);
return -1;
}
-
+
if (!fSuccess)
{
DoOutputErrorString("DebuggerLaunch: ReadFile from pipe failed");
@@ -3295,13 +3312,13 @@ DWORD WINAPI DebuggerLaunch(LPVOID lpParam)
else
DoOutputDebugString("DebuggerLaunch: Read updated EP from pipe: 0x%p\n", OEP);
}
-
+
ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFO));
VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&VersionInfo);
NT5 = (VersionInfo.dwMajorVersion == 5);
-
+
if (NT5)
{
DoOutputDebugString("NT5: Leaving debugger thread alive.\n");
@@ -3312,8 +3329,8 @@ DWORD WINAPI DebuggerLaunch(LPVOID lpParam)
}
DoOutputDebugString("NT6+: Terminating debugger thread.\n");
-
- return 0;
+
+ return 0;
}
//**************************************************************************************
@@ -3326,21 +3343,21 @@ int launch_debugger()
HANDLE hDebuggerLaunch;
hDebuggerLaunch = CreateThread(
- NULL,
- 0,
+ NULL,
+ 0,
DebuggerLaunch,
- NULL,
- 0,
- &NewThreadId);
+ NULL,
+ 0,
+ &NewThreadId);
- if (hDebuggerLaunch == NULL)
+ if (hDebuggerLaunch == NULL)
{
DoOutputDebugString("CAPE: Failed to create debugger launch thread.\n");
return 0;
}
-
+
DoOutputDebugString("CAPE: Launching debugger.\n");
-
+
CloseHandle(hDebuggerLaunch);
return 1;
@@ -3348,7 +3365,23 @@ int launch_debugger()
else
{
DebuggerInitialised = InitialiseDebugger();
-
+
return DebuggerInitialised;
}
+}
+
+void NtContinueHandler(PCONTEXT ThreadContext)
+{
+ if (!ThreadContext->Dr0 && !ThreadContext->Dr1 && !ThreadContext->Dr2 && !ThreadContext->Dr3)
+ {
+ DWORD ThreadId = GetCurrentThreadId();
+ if (ThreadId == MainThreadId)
+ {
+ PTHREADBREAKPOINTS ThreadBreakpoints = GetThreadBreakpoints(ThreadId);
+ if (ThreadBreakpoints) {
+ DoOutputDebugString("NtContinue hook: restoring breakpoints for thread %d.\n", ThreadId);
+ ContextSetThreadBreakpointsEx(ThreadContext, ThreadBreakpoints, TRUE);
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/CAPE/Debugger.h b/CAPE/Debugger.h
index e34156f..e70f64d 100644
--- a/CAPE/Debugger.h
+++ b/CAPE/Debugger.h
@@ -3,6 +3,7 @@
#define DEBUGGER_LAUNCHER 0
#define DisableThreadSuspend 0
+//#define BRANCH_TRACE
#define BP_EXEC 0x00
#define BP_WRITE 0x01
@@ -19,12 +20,14 @@
#define EXTRACTION_MIN_SIZE 0x1001
+#if (NTDDI_VERSION <= NTDDI_WINBLUE)
typedef struct _EXCEPTION_REGISTRATION_RECORD {
struct _EXCEPTION_REGISTRATION_RECORD *Next;
PEXCEPTION_ROUTINE Handler;
} EXCEPTION_REGISTRATION_RECORD;
typedef EXCEPTION_REGISTRATION_RECORD *PEXCEPTION_REGISTRATION_RECORD;
+#endif
typedef struct BreakpointInfo
{
@@ -97,8 +100,8 @@ extern "C" {
BOOL DebuggerInitialised;
// Global variables for submission options
-void *CAPE_var1, *CAPE_var2, *CAPE_var3, *CAPE_var4;
PVOID bp0, bp1, bp2, bp3;
+PVOID bpw0, bpw1, bpw2, bpw3;
LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo);
PVOID CAPEExceptionFilterHandle;
@@ -107,7 +110,7 @@ PEXCEPTION_ROUTINE SEH_TopLevelHandler;
LPTOP_LEVEL_EXCEPTION_FILTER OriginalExceptionHandler;
BOOL VECTORED_HANDLER;
BOOL GuardPagesDisabled;
-
+BOOL DisableSetThreadContext;
DWORD ChildProcessId;
DWORD ChildThreadId;
DWORD_PTR DebuggerEP;
@@ -119,13 +122,22 @@ int launch_debugger(void);
BOOL SetBreakpoint(int Register, int Size, LPVOID Address, DWORD Type, PVOID Callback);
BOOL SetThreadBreakpoint(DWORD ThreadId, int Register, int Size, LPVOID Address, DWORD Type, PVOID Callback);
BOOL ContextSetThreadBreakpoint(PCONTEXT Context, int Register, int Size, LPVOID Address, DWORD Type, PVOID Callback);
+BOOL ContextSetDebugRegister(PCONTEXT Context, int Register, int Size, LPVOID Address, DWORD Type);
+BOOL ContextSetDebugRegisterEx(PCONTEXT Context, int Register, int Size, LPVOID Address, DWORD Type, BOOL NoSetThreadContext);
BOOL SetThreadBreakpoints(PTHREADBREAKPOINTS ThreadBreakpoints);
+BOOL ContextSetThreadBreakpoints(PCONTEXT ThreadContext, PTHREADBREAKPOINTS ThreadBreakpoints);
+BOOL ContextSetThreadBreakpointsEx(PCONTEXT ThreadContext, PTHREADBREAKPOINTS ThreadBreakpoints, BOOL NoSetThreadContext);
BOOL ContextSetBreakpoint(PTHREADBREAKPOINTS ThreadBreakpoints);
BOOL ContextUpdateCurrentBreakpoint(PCONTEXT Context, int Size, LPVOID Address, DWORD Type, PVOID Callback);
BOOL SetNextAvailableBreakpoint(DWORD ThreadId, unsigned int* Register, int Size, LPVOID Address, DWORD Type, PVOID Callback);
BOOL SetSingleStepMode(PCONTEXT Context, PVOID Handler);
BOOL SetResumeFlag(PCONTEXT Context);
BOOL SetZeroFlag(PCONTEXT Context);
+BOOL ClearZeroFlag(PCONTEXT Context);
+BOOL FlipZeroFlag(PCONTEXT Context);
+BOOL SetSignFlag(PCONTEXT Context);
+BOOL ClearSignFlag(PCONTEXT Context);
+BOOL FlipSignFlag(PCONTEXT Context);
PTHREADBREAKPOINTS CreateThreadBreakpoints(DWORD ThreadId);
// Get
@@ -136,6 +148,7 @@ BOOL ContextSetNextAvailableBreakpoint(PCONTEXT Context, unsigned int* Register,
int CheckDebugRegister(HANDLE hThread, int Register);
BOOL CheckDebugRegisters(HANDLE hThread, PCONTEXT pContext);
int ContextCheckDebugRegister(CONTEXT Context, int Register);
+BOOL ContextCheckDebugRegisters(PCONTEXT pContext);
HANDLE GetThreadHandle(DWORD ThreadId);
// Clear
diff --git a/CAPE/GetThreadId.c b/CAPE/GetThreadId.c
index 727bf75..db8c136 100644
--- a/CAPE/GetThreadId.c
+++ b/CAPE/GetThreadId.c
@@ -26,7 +26,7 @@ typedef PVOID PTEB;
// Thread Information Classes
//
-typedef enum _THREADINFOCLASS
+typedef enum _THREADINFOCLASS
{
ThreadBasicInformation,
ThreadTimes,
@@ -52,7 +52,7 @@ typedef enum _THREADINFOCLASS
MaxThreadInfoClass
} THREADINFOCLASS;
-typedef struct _CLIENT_ID
+typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
@@ -67,7 +67,7 @@ typedef struct _CLIENT_ID
// NtQueryInformationThread using ThreadBasicInfo
//
-typedef struct _THREAD_BASIC_INFORMATION
+typedef struct _THREAD_BASIC_INFORMATION
{
NTSTATUS ExitStatus;
PTEB TebBaseAddress;
@@ -115,7 +115,7 @@ DWORD MyGetThreadId
return 0;
}
- FreeLibrary(hModule);
-
+ FreeLibrary(hModule);
+
return (DWORD)(UINT_PTR)ThreadBasicInfo.ClientId.UniqueThread;
}
diff --git a/CAPE/Output.c b/CAPE/Output.c
index 915fcc7..5f56c73 100644
--- a/CAPE/Output.c
+++ b/CAPE/Output.c
@@ -15,41 +15,55 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see .
*/
+#include
#include
#include
#include
+#include
#include "cape.h"
#include "..\pipe.h"
#include "..\config.h"
#define MAX_INT_STRING_LEN 10 // 4294967294
-TCHAR DebugOutput[MAX_PATH];
-TCHAR PipeOutput[MAX_PATH];
-TCHAR ErrorOutput[MAX_PATH];
+CHAR DebugOutput[MAX_PATH];
+CHAR PipeOutput[MAX_PATH];
+CHAR ErrorOutput[MAX_PATH];
+CHAR DebuggerLine[MAX_PATH];
+extern char* GetResultsPath(char* FolderName);
extern struct CapeMetadata *CapeMetaData;
extern ULONG_PTR base_of_dll_of_interest;
+#ifdef CAPE_TRACE
+HANDLE DebuggerLog;
+extern SIZE_T LastWriteLength;
+extern BOOL StopTrace;
+#endif
//**************************************************************************************
-void DoOutputDebugString(_In_ LPCTSTR lpOutputString, ...)
+void OutputString(_In_ LPCTSTR lpOutputString, va_list args)
//**************************************************************************************
{
- va_list args;
-
- va_start(args, lpOutputString);
-
- memset(DebugOutput, 0, MAX_PATH*sizeof(TCHAR));
- _vsntprintf_s(DebugOutput, MAX_PATH, MAX_PATH, lpOutputString, args);
+ memset(DebugOutput, 0, MAX_PATH*sizeof(CHAR));
+ _vsntprintf_s(DebugOutput, MAX_PATH, _TRUNCATE, lpOutputString, args);
#ifdef STANDALONE
OutputDebugString(DebugOutput);
#else
- memset(PipeOutput, 0, MAX_PATH*sizeof(TCHAR));
- _sntprintf_s(PipeOutput, MAX_PATH, MAX_PATH, "DEBUG:%s", DebugOutput);
+ memset(PipeOutput, 0, MAX_PATH*sizeof(CHAR));
+ _sntprintf_s(PipeOutput, MAX_PATH, _TRUNCATE, "DEBUG:%s", DebugOutput);
pipe(PipeOutput, strlen(PipeOutput));
#endif
- va_end(args);
+ return;
+}
+//**************************************************************************************
+void DoOutputDebugString(_In_ LPCTSTR lpOutputString, ...)
+//**************************************************************************************
+{
+ va_list args;
+ va_start(args, lpOutputString);
+ OutputString(lpOutputString, args);
+ va_end(args);
return;
}
@@ -59,9 +73,9 @@ void DoOutputErrorString(_In_ LPCTSTR lpOutputString, ...)
{
va_list args;
LPVOID lpMsgBuf;
- DWORD ErrorCode;
+ DWORD ErrorCode;
- ErrorCode = GetLastError();
+ ErrorCode = GetLastError();
va_start(args, lpOutputString);
FormatMessage(
@@ -70,22 +84,22 @@ void DoOutputErrorString(_In_ LPCTSTR lpOutputString, ...)
ErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
- 0,
+ 0,
NULL);
-
- memset(DebugOutput, 0, MAX_PATH*sizeof(TCHAR));
- _vsntprintf_s(DebugOutput, MAX_PATH, MAX_PATH, lpOutputString, args);
-
- memset(ErrorOutput, 0, MAX_PATH*sizeof(TCHAR));
- _sntprintf_s(ErrorOutput, MAX_PATH, MAX_PATH, "Error %d (0x%x) - %s: %s", ErrorCode, ErrorCode, DebugOutput, (char*)lpMsgBuf);
+
+ memset(DebugOutput, 0, MAX_PATH*sizeof(CHAR));
+ _vsntprintf_s(DebugOutput, MAX_PATH, _TRUNCATE, lpOutputString, args);
+
+ memset(ErrorOutput, 0, MAX_PATH*sizeof(CHAR));
+ _sntprintf_s(ErrorOutput, MAX_PATH, _TRUNCATE, "Error %d (0x%x) - %s: %s", ErrorCode, ErrorCode, DebugOutput, (char*)lpMsgBuf);
#ifdef STANDALONE
OutputDebugString(ErrorOutput);
#else
- memset(PipeOutput, 0, MAX_PATH*sizeof(TCHAR));
- _sntprintf_s(PipeOutput, MAX_PATH, MAX_PATH, "DEBUG:%s", ErrorOutput);
+ memset(PipeOutput, 0, MAX_PATH*sizeof(CHAR));
+ _sntprintf_s(PipeOutput, MAX_PATH, _TRUNCATE, "DEBUG:%s", ErrorOutput);
pipe(PipeOutput, strlen(PipeOutput));
#endif
-
+
va_end(args);
return;
@@ -103,7 +117,7 @@ void CapeOutputFile(_In_ LPCTSTR lpOutputFile)
if (CapeMetaData && CapeMetaData->DumpType == PROCDUMP)
{
- memset(MetadataPath, 0, MAX_PATH * sizeof(TCHAR));
+ memset(MetadataPath, 0, MAX_PATH * sizeof(CHAR));
_sntprintf_s(MetadataPath, MAX_PATH, MAX_PATH, "%s_info.txt", lpOutputFile);
hMetadata = CreateFile(MetadataPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -116,8 +130,8 @@ void CapeOutputFile(_In_ LPCTSTR lpOutputFile)
if (hMetadata == INVALID_HANDLE_VALUE)
{
DoOutputErrorString("Could not create CAPE metadata file");
- return;
- }
+ return;
+ }
BufferSize = 3 * (MAX_PATH + MAX_INT_STRING_LEN + 2) + 2; //// max size string can be
@@ -131,13 +145,13 @@ void CapeOutputFile(_In_ LPCTSTR lpOutputFile)
DoOutputDebugString("CAPE Error: g_config.file_of_interest is NULL.\n", g_config.file_of_interest);
return;
}
-
+
CapeMetaData->ModulePath = (char*)malloc(MAX_PATH);
WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, (LPCWSTR)g_config.file_of_interest, (int)wcslen(g_config.file_of_interest)+1, CapeMetaData->ModulePath, MAX_PATH, NULL, NULL);
}
else
CapeMetaData->ModulePath = CapeMetaData->ProcessPath;
-
+
// This metadata format is specific to process dumps
_snprintf_s(Buffer, BufferSize, BufferSize, "%d\n%d\n%s\n%s\n", CapeMetaData->DumpType, CapeMetaData->Pid, CapeMetaData->ProcessPath, CapeMetaData->ModulePath);
@@ -150,13 +164,13 @@ void CapeOutputFile(_In_ LPCTSTR lpOutputFile)
}
CloseHandle(hMetadata);
-
- memset(DebugOutput, 0, MAX_PATH*sizeof(TCHAR));
+
+ memset(DebugOutput, 0, MAX_PATH*sizeof(CHAR));
_sntprintf_s(DebugOutput, MAX_PATH, MAX_PATH, "Process dump output file: %s", lpOutputFile);
#ifdef STANDALONE
OutputDebugString(DebugOutput);
#else
- memset(PipeOutput, 0, MAX_PATH*sizeof(TCHAR));
+ memset(PipeOutput, 0, MAX_PATH*sizeof(CHAR));
_sntprintf_s(PipeOutput, MAX_PATH, MAX_PATH, "FILE_DUMP:%s", lpOutputFile);
pipe(PipeOutput, strlen(PipeOutput));
#endif
@@ -164,7 +178,7 @@ void CapeOutputFile(_In_ LPCTSTR lpOutputFile)
}
else if (CapeMetaData && CapeMetaData->DumpType != PROCDUMP)
{
- memset(MetadataPath, 0, MAX_PATH * sizeof(TCHAR));
+ memset(MetadataPath, 0, MAX_PATH * sizeof(CHAR));
_sntprintf_s(MetadataPath, MAX_PATH, MAX_PATH, "%s_info.txt", lpOutputFile);
hMetadata = CreateFile(MetadataPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -177,15 +191,17 @@ void CapeOutputFile(_In_ LPCTSTR lpOutputFile)
if (hMetadata == INVALID_HANDLE_VALUE)
{
DoOutputErrorString("Could not create CAPE metadata file");
- return;
- }
+ return;
+ }
BufferSize = 3 * (MAX_PATH + MAX_INT_STRING_LEN + 2) + 2; //// max size string can be
Buffer = malloc(BufferSize);
+ if (!CapeMetaData->ProcessPath)
+ CapeMetaData->ProcessPath = "Unknown path";
CapeMetaData->ModulePath = CapeMetaData->ProcessPath;
-
+
if (CapeMetaData->DumpType == EXTRACTION_PE || CapeMetaData->DumpType == EXTRACTION_SHELLCODE)
{
// Extraction-specific format
@@ -215,19 +231,99 @@ void CapeOutputFile(_In_ LPCTSTR lpOutputFile)
}
CloseHandle(hMetadata);
-
- memset(DebugOutput, 0, MAX_PATH*sizeof(TCHAR));
+
+ memset(DebugOutput, 0, MAX_PATH*sizeof(CHAR));
_sntprintf_s(DebugOutput, MAX_PATH, MAX_PATH, "CAPE Output file: %s", lpOutputFile);
#ifdef STANDALONE
OutputDebugString(DebugOutput);
#else
- memset(PipeOutput, 0, MAX_PATH*sizeof(TCHAR));
+ memset(PipeOutput, 0, MAX_PATH*sizeof(CHAR));
_sntprintf_s(PipeOutput, MAX_PATH, MAX_PATH, "FILE_CAPE:%s", lpOutputFile);
pipe(PipeOutput, strlen(PipeOutput));
#endif
}
else
DoOutputDebugString("No CAPE metadata (or wrong type) for file: %s\n", lpOutputFile);
-
+
return;
}
+
+#ifdef CAPE_TRACE
+//**************************************************************************************
+void DebuggerOutput(_In_ LPCTSTR lpOutputString, ...)
+//**************************************************************************************
+{
+ va_list args;
+
+ va_start(args, lpOutputString);
+
+ if (g_config.divert_debugger_log)
+ {
+ OutputString(lpOutputString, args);
+ va_end(args);
+ return;
+ }
+
+ char *FullPathName, *OutputFilename, *Character;
+
+ FullPathName = GetResultsPath("debugger");
+
+ OutputFilename = (char*)malloc(MAX_PATH);
+
+ if (OutputFilename == NULL)
+ {
+ DoOutputErrorString("DebuggerOutput: failed to allocate memory for file name string");
+ return;
+ }
+
+ sprintf_s(OutputFilename, MAX_PATH, "%d.log", GetCurrentProcessId());
+
+ PathAppend(FullPathName, OutputFilename);
+
+ free(OutputFilename);
+
+ if (!DebuggerLog && !StopTrace)
+ {
+ time_t Time;
+ CHAR TimeBuffer[64];
+
+ DebuggerLog = CreateFile(FullPathName, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (DebuggerLog == INVALID_HANDLE_VALUE)
+ {
+ DoOutputErrorString("DebuggerOutput: Unable to open debugger logfile %s.\n", FullPathName);
+ return;
+ }
+ DoOutputDebugString("DebuggerOutput: Debugger logfile %s.\n", FullPathName);
+
+ time(&Time);
+ memset(DebuggerLine, 0, MAX_PATH*sizeof(CHAR));
+ ctime_s(TimeBuffer, 64, (const time_t *)&Time);
+ _snprintf_s(DebuggerLine, MAX_PATH, _TRUNCATE, "CAPE Sandbox - Debugger log: %s" , TimeBuffer);
+ WriteFile(DebuggerLog, DebuggerLine, (DWORD)strlen(DebuggerLine), (LPDWORD)&LastWriteLength, NULL);
+ while (*lpOutputString == 0x0a)
+ lpOutputString++;
+ }
+ else if (StopTrace)
+ {
+ CloseHandle(DebuggerLog);
+ va_end(args);
+ return;
+ }
+
+ memset(DebuggerLine, 0, MAX_PATH*sizeof(CHAR));
+ _vsnprintf_s(DebuggerLine, MAX_PATH, _TRUNCATE, lpOutputString, args);
+ Character = DebuggerLine;
+ while (*Character)
+ { // Restrict to ASCII range
+ if (*Character < 0x0a || *Character > 0x7E)
+ *Character = 0x3F; // '?'
+ Character++;
+ }
+ WriteFile(DebuggerLog, DebuggerLine, (DWORD)strlen(DebuggerLine), (LPDWORD)&LastWriteLength, NULL);
+
+ va_end(args);
+
+ return;
+}
+#endif
diff --git a/CAPE/QakBot.c b/CAPE/QakBot.c
new file mode 100644
index 0000000..c7d29fc
--- /dev/null
+++ b/CAPE/QakBot.c
@@ -0,0 +1,522 @@
+/*
+CAPE - Config And Payload Extraction
+Copyright(C) 2015 - 2018 Context Information Security. (kevin.oreilly@contextis.com)
+
+This program is free software : you can redistribute it and / or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.If not, see .
+*/
+#include
+#include "..\hooking.h"
+#include "Debugger.h"
+#include "CAPE.h"
+
+#define MAX_INSTRUCTIONS 0x10
+#define SINGLE_STEP_LIMIT 0x80 // default unless specified in web ui
+#define CHUNKSIZE 0x10 * MAX_INSTRUCTIONS
+
+extern void DoOutputDebugString(_In_ LPCTSTR lpOutputString, ...);
+extern void DoOutputErrorString(_In_ LPCTSTR lpOutputString, ...);
+extern int DumpModuleInCurrentProcess(LPVOID ModuleBase);
+extern int DumpMemory(LPVOID Buffer, SIZE_T Size);
+extern char *convert_address_to_dll_name_and_offset(ULONG_PTR addr, unsigned int *offset);
+extern DWORD_PTR FileOffsetToVA(DWORD_PTR modBase, DWORD_PTR dwOffset);
+extern BOOL ScyllaGetSectionByName(PVOID ImageBase, char* Name, PVOID* SectionData, SIZE_T* SectionSize);
+
+char *ModuleName, *PreviousModuleName;
+BOOL BreakpointsSet, BreakpointsHit, FilterTrace, TraceAll, StopTrace, DllPrinted;
+PVOID ModuleBase, DumpAddress;
+BOOL GetSystemTimeAsFileTimeImported, PayloadMarker, PayloadDumped, TraceRunning;
+unsigned int DumpCount, Correction, StepCount, StepLimit, TraceDepthLimit;
+char Action0[MAX_PATH], Action1[MAX_PATH], Action2[MAX_PATH], Action3[MAX_PATH], *Instruction0, *Instruction1, *Instruction2, *Instruction3;
+unsigned int Type0, Type1, Type2, Type3;
+int StepOverRegister, TraceDepthCount, EntryPointRegister;
+CONTEXT LastContext;
+SIZE_T DumpSize, LastWriteLength;
+char DumpSizeString[MAX_PATH], DebuggerBuffer[MAX_PATH];
+
+BOOL Trace(struct _EXCEPTION_POINTERS* ExceptionInfo);
+BOOL Trace2(struct _EXCEPTION_POINTERS* ExceptionInfo);
+BOOL BreakpointCallback1(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo);
+BOOL BreakpointCallback2(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo);
+BOOL BreakpointCallback3(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo);
+
+BOOL DoSetSingleStepMode(int Register, PCONTEXT Context, PVOID Handler)
+{
+ StepOverRegister = Register;
+ return SetSingleStepMode(Context, Trace);
+}
+
+BOOL Trace(struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ PVOID ReturnAddress;
+ char* DllName;
+ unsigned int DllRVA;
+
+ _DecodeResult Result;
+ _OffsetType Offset = 0;
+ _DecodedInst DecodedInstruction;
+ unsigned int DecodedInstructionsCount = 0;
+
+ StepCount++;
+
+ if (StepCount > StepLimit)
+ {
+ DoOutputDebugString("Trace: single-step limit reached (%d), releasing.", StepLimit);
+ return TRUE;
+ }
+
+#ifdef _WIN64
+ DllName = convert_address_to_dll_name_and_offset((ULONG_PTR)ExceptionInfo->ContextRecord->Rip, &DllRVA);
+ _DecodeType DecodeType = Decode64Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)ExceptionInfo->ContextRecord->Rip, CHUNKSIZE, DecodeType, &DecodedInstruction, 1, &DecodedInstructionsCount);
+ DoOutputDebugString("0x%p (%02d) %-24s %s%s%s\n", ExceptionInfo->ContextRecord->Rip, DecodedInstruction.size, (char*)DecodedInstruction.instructionHex.p, (char*)DecodedInstruction.mnemonic.p, DecodedInstruction.operands.length != 0 ? " " : "", (char*)DecodedInstruction.operands.p);
+#else
+ DllName = convert_address_to_dll_name_and_offset((ULONG_PTR)ExceptionInfo->ContextRecord->Eip, &DllRVA);
+ _DecodeType DecodeType = Decode32Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)ExceptionInfo->ContextRecord->Eip, CHUNKSIZE, DecodeType, &DecodedInstruction, 1, &DecodedInstructionsCount);
+ DoOutputDebugString("0x%x (%02d) %-24s %s%s%s\n", ExceptionInfo->ContextRecord->Eip, DecodedInstruction.size, (char*)DecodedInstruction.instructionHex.p, (char*)DecodedInstruction.mnemonic.p, DecodedInstruction.operands.length != 0 ? " " : "", (char*)DecodedInstruction.operands.p);
+#endif
+
+ if (!DllPrinted && DllName)
+ {
+ DoOutputDebugString("Trace: Tracing in %s (RVA 0x%x).\n", DllName, DllRVA);
+ DllPrinted = TRUE;
+ }
+
+ if (!strcmp(DecodedInstruction.mnemonic.p, "CALL"))
+ {
+ if (TraceDepthCount >= TraceDepthLimit)
+ {
+#ifdef _WIN64
+ ReturnAddress = (PVOID)((PUCHAR)ExceptionInfo->ContextRecord->Rip + DecodedInstruction.size);
+#else
+ ReturnAddress = (PVOID)((PUCHAR)ExceptionInfo->ContextRecord->Eip + DecodedInstruction.size);
+#endif
+ if (!ContextSetThreadBreakpoint(ExceptionInfo->ContextRecord, StepOverRegister, 0, (BYTE*)ReturnAddress, BP_EXEC, BreakpointCallback1))
+ {
+ DoOutputDebugString("Trace: Failed to set breakpoint on return address 0x%p\n", ReturnAddress);
+ }
+
+ ClearSingleStepMode(ExceptionInfo->ContextRecord);
+
+ return TRUE;
+ }
+ else
+ TraceDepthCount++;
+ }
+ else if (!strcmp(DecodedInstruction.mnemonic.p, "RET"))
+ {
+ if (TraceDepthCount < 0)
+ {
+ DoOutputDebugString("Trace: Stepping out of initial depth, releasing.");
+
+ ClearSingleStepMode(ExceptionInfo->ContextRecord);
+
+ return TRUE;
+ }
+
+ TraceDepthCount--;
+ }
+ else if (!strcmp(DecodedInstruction.mnemonic.p, "JLE"))
+ {
+ DoOutputDebugString("Trace: JLE detected, clearing zero flag.\n");
+ ClearZeroFlag(ExceptionInfo->ContextRecord);
+ }
+
+ SetSingleStepMode(ExceptionInfo->ContextRecord, Trace);
+
+ return TRUE;
+}
+
+BOOL Trace2(struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ PVOID ReturnAddress;
+ char* DllName;
+ unsigned int DllRVA;
+
+ _DecodeResult Result;
+ _OffsetType Offset = 0;
+ _DecodedInst DecodedInstruction;
+ unsigned int DecodedInstructionsCount = 0;
+
+ StepCount++;
+
+ if (StepCount > StepLimit)
+ {
+ DoOutputDebugString("Trace2: single-step limit reached (%d), releasing.", StepLimit);
+ return TRUE;
+ }
+
+#ifdef _WIN64
+ DllName = convert_address_to_dll_name_and_offset((ULONG_PTR)ExceptionInfo->ContextRecord->Rip, &DllRVA);
+ _DecodeType DecodeType = Decode64Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)ExceptionInfo->ContextRecord->Rip, CHUNKSIZE, DecodeType, &DecodedInstruction, 1, &DecodedInstructionsCount);
+ DoOutputDebugString("0x%p (%02d) %-24s %s%s%s\n", ExceptionInfo->ContextRecord->Rip, DecodedInstruction.size, (char*)DecodedInstruction.instructionHex.p, (char*)DecodedInstruction.mnemonic.p, DecodedInstruction.operands.length != 0 ? " " : "", (char*)DecodedInstruction.operands.p);
+#else
+ DllName = convert_address_to_dll_name_and_offset((ULONG_PTR)ExceptionInfo->ContextRecord->Eip, &DllRVA);
+ _DecodeType DecodeType = Decode32Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)ExceptionInfo->ContextRecord->Eip, CHUNKSIZE, DecodeType, &DecodedInstruction, 1, &DecodedInstructionsCount);
+ DoOutputDebugString("0x%x (%02d) %-24s %s%s%s\n", ExceptionInfo->ContextRecord->Eip, DecodedInstruction.size, (char*)DecodedInstruction.instructionHex.p, (char*)DecodedInstruction.mnemonic.p, DecodedInstruction.operands.length != 0 ? " " : "", (char*)DecodedInstruction.operands.p);
+#endif
+
+ if (!DllPrinted && DllName)
+ {
+ DoOutputDebugString("Trace2: Tracing in %s (RVA 0x%x).\n", DllName, DllRVA);
+ DllPrinted = TRUE;
+ }
+
+ if (!strcmp(DecodedInstruction.mnemonic.p, "CALL"))
+ {
+ if (TraceDepthCount >= TraceDepthLimit)
+ {
+#ifdef _WIN64
+ ReturnAddress = (PVOID)((PUCHAR)ExceptionInfo->ContextRecord->Rip + DecodedInstruction.size);
+#else
+ ReturnAddress = (PVOID)((PUCHAR)ExceptionInfo->ContextRecord->Eip + DecodedInstruction.size);
+#endif
+ if (!ContextSetThreadBreakpoint(ExceptionInfo->ContextRecord, StepOverRegister, 0, (BYTE*)ReturnAddress, BP_EXEC, BreakpointCallback2))
+ {
+ DoOutputDebugString("Trace2: Failed to set breakpoint on return address 0x%p\n", ReturnAddress);
+ }
+
+ ClearSingleStepMode(ExceptionInfo->ContextRecord);
+
+ return TRUE;
+ }
+ else
+ TraceDepthCount++;
+ }
+ else if (!strcmp(DecodedInstruction.mnemonic.p, "RET"))
+ {
+ if (TraceDepthCount < 0)
+ {
+ DoOutputDebugString("Trace2: Stepping out of initial depth, releasing.");
+
+ ClearSingleStepMode(ExceptionInfo->ContextRecord);
+
+ return TRUE;
+ }
+
+ TraceDepthCount--;
+ }
+
+ SetSingleStepMode(ExceptionInfo->ContextRecord, Trace);
+
+ return TRUE;
+}
+
+BOOL BreakpointCallback1(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ _DecodeResult Result;
+ _OffsetType Offset = 0;
+ _DecodedInst DecodedInstruction;
+ unsigned int DecodedInstructionsCount = 0;
+
+ if (pBreakpointInfo == NULL)
+ {
+ DoOutputDebugString("BreakpointCallback1 executed with pBreakpointInfo NULL.\n");
+ return FALSE;
+ }
+
+ if (pBreakpointInfo->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("BreakpointCallback1 executed with NULL thread handle.\n");
+ return FALSE;
+ }
+
+#ifdef _WIN64
+ _DecodeType DecodeType = Decode64Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)ExceptionInfo->ContextRecord->Rip, CHUNKSIZE, DecodeType, &DecodedInstruction, 1, &DecodedInstructionsCount);
+ DoOutputDebugString("0x%p (%02d) %-24s %s%s%s\n", ExceptionInfo->ContextRecord->Rip, DecodedInstruction.size, (char*)DecodedInstruction.instructionHex.p, (char*)DecodedInstruction.mnemonic.p, DecodedInstruction.operands.length != 0 ? " " : "", (char*)DecodedInstruction.operands.p);
+#else
+ _DecodeType DecodeType = Decode32Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)ExceptionInfo->ContextRecord->Eip, CHUNKSIZE, DecodeType, &DecodedInstruction, 1, &DecodedInstructionsCount);
+ DoOutputDebugString("0x%x (%02d) %-24s %s%s%s\n", ExceptionInfo->ContextRecord->Eip, DecodedInstruction.size, (char*)DecodedInstruction.instructionHex.p, (char*)DecodedInstruction.mnemonic.p, DecodedInstruction.operands.length != 0 ? " " : "", (char*)DecodedInstruction.operands.p);
+#endif
+
+ if (!strcmp(DecodedInstruction.mnemonic.p, "JLE"))
+ {
+ DoOutputDebugString("Trace: JLE detected, clearing zero flag to bypass anti-sandbox.\n");
+ ClearZeroFlag(ExceptionInfo->ContextRecord);
+ }
+
+ StepOverExecutionBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo);
+
+ DoSetSingleStepMode(pBreakpointInfo->Register, ExceptionInfo->ContextRecord, Trace);
+
+ return TRUE;
+}
+
+BOOL BreakpointCallback2(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ _DecodeResult Result;
+ _OffsetType Offset = 0;
+ _DecodedInst DecodedInstruction;
+ unsigned int DecodedInstructionsCount = 0;
+
+ if (pBreakpointInfo == NULL)
+ {
+ DoOutputDebugString("BreakpointCallback2 executed with pBreakpointInfo NULL.\n");
+ return FALSE;
+ }
+
+ if (pBreakpointInfo->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("BreakpointCallback2 executed with NULL thread handle.\n");
+ return FALSE;
+ }
+
+#ifdef _WIN64
+ _DecodeType DecodeType = Decode64Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)ExceptionInfo->ContextRecord->Rip, CHUNKSIZE, DecodeType, &DecodedInstruction, 1, &DecodedInstructionsCount);
+ DoOutputDebugString("0x%p (%02d) %-24s %s%s%s\n", ExceptionInfo->ContextRecord->Rip, DecodedInstruction.size, (char*)DecodedInstruction.instructionHex.p, (char*)DecodedInstruction.mnemonic.p, DecodedInstruction.operands.length != 0 ? " " : "", (char*)DecodedInstruction.operands.p);
+#else
+ _DecodeType DecodeType = Decode32Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)ExceptionInfo->ContextRecord->Eip, CHUNKSIZE, DecodeType, &DecodedInstruction, 1, &DecodedInstructionsCount);
+ DoOutputDebugString("0x%x (%02d) %-24s %s%s%s\n", ExceptionInfo->ContextRecord->Eip, DecodedInstruction.size, (char*)DecodedInstruction.instructionHex.p, (char*)DecodedInstruction.mnemonic.p, DecodedInstruction.operands.length != 0 ? " " : "", (char*)DecodedInstruction.operands.p);
+#endif
+
+ if (!strcmp(DecodedInstruction.mnemonic.p, "CALL"))
+ {
+ DumpSize = (SIZE_T)*(DWORD*)((BYTE*)ExceptionInfo->ContextRecord->Esp+4*3);
+ DumpAddress = (PVOID)*(DWORD*)((BYTE*)ExceptionInfo->ContextRecord->Esp+4*4);
+
+ DoOutputDebugString("Trace: CALL detected, grabbing size 0x%x and buffer 0x%x from stack.\n", DumpSize, DumpAddress);
+
+ if (DumpSize > 0x1000)
+ DoOutputDebugString("Trace: Size too big, not the config.\n");
+ else if (!ContextSetThreadBreakpoint(ExceptionInfo->ContextRecord, 2, 0, ((BYTE*)ExceptionInfo->ContextRecord->Eip)+5, BP_EXEC, BreakpointCallback3))
+ DoOutputDebugString("Trace: failed to set breakpoint on call return at 0x%x", ((BYTE*)ExceptionInfo->ContextRecord->Eip)+5);
+ }
+
+ StepOverExecutionBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo);
+
+ return TRUE;
+}
+
+BOOL BreakpointCallback3(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ _DecodeResult Result;
+ _OffsetType Offset = 0;
+ _DecodedInst DecodedInstruction;
+ unsigned int DecodedInstructionsCount = 0;
+
+ if (pBreakpointInfo == NULL)
+ {
+ DoOutputDebugString("BreakpointCallback3 executed with pBreakpointInfo NULL.\n");
+ return FALSE;
+ }
+
+ if (pBreakpointInfo->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("BreakpointCallback3 executed with NULL thread handle.\n");
+ return FALSE;
+ }
+
+#ifdef _WIN64
+ _DecodeType DecodeType = Decode64Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)ExceptionInfo->ContextRecord->Rip, CHUNKSIZE, DecodeType, &DecodedInstruction, 1, &DecodedInstructionsCount);
+ DoOutputDebugString("0x%p (%02d) %-24s %s%s%s\n", ExceptionInfo->ContextRecord->Rip, DecodedInstruction.size, (char*)DecodedInstruction.instructionHex.p, (char*)DecodedInstruction.mnemonic.p, DecodedInstruction.operands.length != 0 ? " " : "", (char*)DecodedInstruction.operands.p);
+#else
+ _DecodeType DecodeType = Decode32Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)ExceptionInfo->ContextRecord->Eip, CHUNKSIZE, DecodeType, &DecodedInstruction, 1, &DecodedInstructionsCount);
+ DoOutputDebugString("0x%x (%02d) %-24s %s%s%s\n", ExceptionInfo-> ContextRecord->Eip, DecodedInstruction.size, (char*)DecodedInstruction.instructionHex.p, (char*)DecodedInstruction.mnemonic.p, DecodedInstruction.operands.length != 0 ? " " : "", (char*)DecodedInstruction.operands.p);
+#endif
+
+ if (DumpSize && DumpAddress && DumpCount < 1)
+ {
+ CapeMetaData->DumpType = QAKBOT_CONFIG;
+ if (DumpMemory(DumpAddress, DumpSize))
+ {
+ DoOutputDebugString("Trace: dumped QakBot config from 0x%x.\n", DumpAddress);
+ DumpCount+=1;
+ }
+ else
+ DoOutputDebugString("Trace: Error - failed to dump config from: 0x%x.\n", DumpAddress);
+ }
+ else
+ DoOutputDebugString("Trace: Error - dump size or dump address not set: 0x%x, 0x%x.\n", DumpAddress, DumpSize);
+
+ ContextClearCurrentBreakpoint(ExceptionInfo->ContextRecord);
+
+ StepOverExecutionBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo);
+
+ return TRUE;
+}
+
+BOOL SetInitialBreakpoints(PVOID ImageBase)
+{
+ _DecodeResult Result;
+ _OffsetType Offset = 0;
+ _DecodedInst DecodedInstructions[MAX_INSTRUCTIONS];
+ unsigned int DecodedInstructionsCount = 0, ChunkSize, Delta = 0;
+
+ DWORD_PTR BreakpointVA;
+ DWORD Register = 0, ThreadId = GetCurrentThreadId();
+
+ DumpCount = 0;
+ StepCount = 0;
+ TraceDepthCount = 0;
+
+ if (!StepLimit)
+ StepLimit = SINGLE_STEP_LIMIT;
+
+ if (!bp0 && !bp1 && !bp2)// && !bp3)
+ {
+ DoOutputDebugString("SetInitialBreakpoints: Error - No address specified for QakBot breakpoints.\n");
+ return FALSE;
+ }
+
+ if (!ImageBase)
+ {
+ ImageBase = GetModuleHandle(NULL);
+ DoOutputDebugString("SetInitialBreakpoints: ImageBase not set by base-on-api parameter, defaulting to process image base 0x%p.\n", ImageBase);
+ return FALSE;
+ }
+ else
+ DoOutputDebugString("SetInitialBreakpoints: ImageBase set to 0x%p.\n", ImageBase);
+
+ BreakpointsSet = FALSE;
+
+ if (bp0)
+ {
+ Delta = 0;
+ Register = 0;
+ BreakpointVA = FileOffsetToVA((DWORD_PTR)ImageBase, (DWORD_PTR)bp0);
+
+ ChunkSize = 0x80; // Size of code to disassemble
+ memset(&DecodedInstructions, 0, sizeof(DecodedInstructions));
+
+ _DecodeType DecodeType = Decode32Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)BreakpointVA, ChunkSize, DecodeType, DecodedInstructions, 1, &DecodedInstructionsCount);
+
+ for (unsigned int i = 0; i < DecodedInstructionsCount; i++)
+ {
+ DoOutputDebugString("0x%x (%02d) %-24s %s%s%s\n", BreakpointVA + Delta, DecodedInstructions[i].size, (char*)DecodedInstructions[i].instructionHex.p, (char*)DecodedInstructions[i].mnemonic.p, DecodedInstructions[i].operands.length != 0 ? " " : "", (char*)DecodedInstructions[i].operands.p);
+
+ if (!strcmp(DecodedInstructions[i].mnemonic.p, "JLE"))
+ {
+ if (SetBreakpoint(Register, 0, (BYTE*)BreakpointVA + Delta, BP_EXEC, BreakpointCallback1))
+ {
+ DoOutputDebugString("SetInitialBreakpoint: Breakpoint %d set on jle instruction at 0x%x.\n", Register, (BYTE*)BreakpointVA + Delta);
+ BreakpointsSet = TRUE;
+ break;
+ }
+ else
+ {
+ DoOutputDebugString("SetInitialBreakpoint: SetBreakpoint failed #1.\n");
+ return FALSE;
+ }
+ }
+
+ Delta += DecodedInstructions[i].size;
+ }
+ }
+ else
+ DoOutputDebugString("SetInitialBreakpoint: No breakpoint supplied for QakBot anti-sandbox bypass.\n");
+
+ if (bp1)
+ {
+ Delta = 0;
+ Register = 1;
+ BreakpointVA = FileOffsetToVA((DWORD_PTR)ImageBase, (DWORD_PTR)bp1);
+
+ ChunkSize = 0x80; // Size of code to disassemble
+ memset(&DecodedInstructions, 0, sizeof(DecodedInstructions));
+
+ _DecodeType DecodeType = Decode32Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)BreakpointVA, ChunkSize, DecodeType, DecodedInstructions, 1, &DecodedInstructionsCount);
+
+ for (unsigned int i = 0; i < DecodedInstructionsCount; i++)
+ {
+ DoOutputDebugString("0x%x (%02d) %-24s %s%s%s\n", BreakpointVA + Delta, DecodedInstructions[i].size, (char*)DecodedInstructions[i].instructionHex.p, (char*)DecodedInstructions[i].mnemonic.p, DecodedInstructions[i].operands.length != 0 ? " " : "", (char*)DecodedInstructions[i].operands.p);
+
+ if (!strcmp(DecodedInstructions[i].mnemonic.p, "CALL"))
+ {
+ if (SetBreakpoint(Register, 0, (BYTE*)BreakpointVA + Delta, BP_EXEC, BreakpointCallback2))
+ {
+ DoOutputDebugString("SetInitialBreakpoint: Breakpoint %d set on call instruction at 0x%x.\n", Register, (BYTE*)BreakpointVA + Delta);
+ BreakpointsSet = TRUE;
+ break;
+ }
+ else
+ {
+ DoOutputDebugString("SetInitialBreakpoint: SetBreakpoint failed #2.\n");
+ return FALSE;
+ }
+ }
+
+ Delta += DecodedInstructions[i].size;
+ }
+ }
+ else
+ DoOutputDebugString("SetInitialBreakpoint: No breakpoint supplied for QakBot primary config dump.\n");
+
+ if (bp2)
+ {
+ Delta = 0;
+ Register = 2;
+ BreakpointVA = FileOffsetToVA((DWORD_PTR)ImageBase, (DWORD_PTR)bp2);
+
+ ChunkSize = 0x80; // Size of code to disassemble
+ memset(&DecodedInstructions, 0, sizeof(DecodedInstructions));
+
+ _DecodeType DecodeType = Decode32Bits;
+ Result = distorm_decode(Offset, (const unsigned char*)BreakpointVA, ChunkSize, DecodeType, DecodedInstructions, 1, &DecodedInstructionsCount);
+
+ for (unsigned int i = 0; i < DecodedInstructionsCount; i++)
+ {
+ DoOutputDebugString("0x%x (%02d) %-24s %s%s%s\n", BreakpointVA + Delta, DecodedInstructions[i].size, (char*)DecodedInstructions[i].instructionHex.p, (char*)DecodedInstructions[i].mnemonic.p, DecodedInstructions[i].operands.length != 0 ? " " : "", (char*)DecodedInstructions[i].operands.p);
+
+ if (!strcmp(DecodedInstructions[i].mnemonic.p, "CALL"))
+ {
+ if (SetBreakpoint(Register, 0, (BYTE*)BreakpointVA + Delta, BP_EXEC, BreakpointCallback2))
+ {
+ DoOutputDebugString("SetInitialBreakpoint: Breakpoint %d set on call instruction at 0x%x.\n", Register, (BYTE*)BreakpointVA + Delta);
+ BreakpointsSet = TRUE;
+ break;
+ }
+ else
+ {
+ DoOutputDebugString("SetInitialBreakpoint: SetBreakpoint failed #2.\n");
+ return FALSE;
+ }
+ }
+
+ Delta += DecodedInstructions[i].size;
+ }
+ }
+ else
+ DoOutputDebugString("SetInitialBreakpoint: No breakpoint supplied for QakBot secondary config dump.\n");
+/*
+ if (bp3)
+ {
+ Register = 3;
+
+ BreakpointVA = (DWORD_PTR)ImageBase + (DWORD_PTR)bp3;
+
+ if (SetBreakpoint(Register, 0, (BYTE*)BreakpointVA, BP_EXEC, BreakpointCallback))
+ {
+ DoOutputDebugString("SetInitialBreakpoints: Breakpoint %d set on address 0x%p (RVA 0x%x)\n", Register, BreakpointVA, bp3);
+ BreakpointsSet = TRUE;
+ }
+ else
+ {
+ DoOutputDebugString("SetInitialBreakpoints: SetBreakpoint failed.\n");
+ BreakpointsSet = FALSE;
+ return FALSE;
+ }
+ }
+*/
+ return BreakpointsSet;
+}
diff --git a/CAPE/Scylla/ApiReader.cpp b/CAPE/Scylla/ApiReader.cpp
index 415aa58..713d2c4 100644
--- a/CAPE/Scylla/ApiReader.cpp
+++ b/CAPE/Scylla/ApiReader.cpp
@@ -389,13 +389,19 @@ void ApiReader::parseExportTable(ModuleInfo *module, PIMAGE_NT_HEADERS pNtHeader
{
DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0;
WORD *addressOfNameOrdinalsArray = 0;
- char *functionName = 0;
+ char *functionName = 0, *directoryName;
DWORD_PTR RVA = 0, VA = 0;
WORD ordinal = 0;
WORD i = 0, j = 0;
bool withoutName;
-
+ if (pExportDir && pExportDir->Name) {
+ directoryName = (char*)((PBYTE)pExportDir->Name + deltaAddress);
+ strncpy_s(module->DirectoryName, directoryName, strlen(directoryName)+1);
+#ifdef DEBUG_COMMENTS
+ DoOutputDebugString("parseExportTable :: pExportDir->Name %s", module->DirectoryName);
+#endif
+ }
addressOfFunctionsArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress);
addressOfNamesArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress);
addressOfNameOrdinalsArray = (WORD *)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress);
diff --git a/CAPE/Scylla/ApiReader.h b/CAPE/Scylla/ApiReader.h
index 45e67ef..54d1431 100644
--- a/CAPE/Scylla/ApiReader.h
+++ b/CAPE/Scylla/ApiReader.h
@@ -29,6 +29,7 @@ class ApiReader : public ProcessAccessHelp
void addFoundApiToModuleList(DWORD_PTR iatAddress, ApiInfo * apiFound, bool isNewModule, bool isSuspect);
void clearAll();
bool isInvalidMemoryForIat( DWORD_PTR address );
+ void parseModuleWithOwnProcess( ModuleInfo * module );
private:
bool readExportTableAlwaysFromDisk;
void parseIAT(DWORD_PTR addressIAT, BYTE * iatBuffer, SIZE_T size);
@@ -49,7 +50,6 @@ class ApiReader : public ProcessAccessHelp
void findApiByModule(ModuleInfo * module, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi);
bool isModuleLoadedInOwnProcess( ModuleInfo * module );
- void parseModuleWithOwnProcess( ModuleInfo * module );
bool isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader);
void findApiInProcess( ModuleInfo * module, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi );
bool findApiInExportTable(ModuleInfo *module, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi);
diff --git a/CAPE/Scylla/IATReferenceScan.cpp b/CAPE/Scylla/IATReferenceScan.cpp
index 471a21d..7e1690e 100644
--- a/CAPE/Scylla/IATReferenceScan.cpp
+++ b/CAPE/Scylla/IATReferenceScan.cpp
@@ -67,8 +67,6 @@ void IATReferenceScan::startScan(DWORD_PTR imageBase, DWORD imageSize, DWORD_PTR
iatDirectImportList.reserve(50);
}
-
-
DWORD_PTR section = imageBase;
do
@@ -410,7 +408,6 @@ void IATReferenceScan::patchNewIat(DWORD_PTR stdImagebase, DWORD_PTR newIatBaseA
}
}
-
void IATReferenceScan::printDirectImportLog()
{
DoOutputDebugString("------------------------------------------------------------");
@@ -455,7 +452,6 @@ void IATReferenceScan::printDirectImportLog()
DoOutputDebugString("------------------------------------------------------------");
}
-
void IATReferenceScan::findDirectIatReferenceCallJmp( _DInst * instruction )
{
IATReference ref;
@@ -735,5 +731,3 @@ DWORD IATReferenceScan::addAdditionalApisToList()
return newIatSize;
}
-
-
diff --git a/CAPE/Scylla/ImportsHandling.cpp b/CAPE/Scylla/ImportsHandling.cpp
index 17c9cda..4724f15 100644
--- a/CAPE/Scylla/ImportsHandling.cpp
+++ b/CAPE/Scylla/ImportsHandling.cpp
@@ -3,12 +3,6 @@
#include "Thunks.h"
#include "Architecture.h"
-#include
-#include
-//#include "multitree.h" // CMultiSelectTreeViewCtrl
-
-//#include "resource.h"
-
//#define DEBUG_COMMENTS
extern "C" void DoOutputDebugString(_In_ LPCTSTR lpOutputString, ...);
@@ -59,59 +53,6 @@ ImportsHandling::ImportsHandling()
ImportsHandling::~ImportsHandling()
{
- //TreeIcons.Destroy();
-}
-
-bool ImportsHandling::isModule(CTreeItem item)
-{
- return (0 != getModuleThunk(item));
-}
-
-bool ImportsHandling::isImport(CTreeItem item)
-{
- return (0 != getImportThunk(item));
-}
-
-ImportModuleThunk * ImportsHandling::getModuleThunk(CTreeItem item)
-{
- stdext::hash_map::const_iterator it;
- it = itemData.find(item);
- if(it != itemData.end())
- {
- const TreeItemData * data = &it->second;
- if(data->isModule)
- {
- return data->module;
- }
- }
- return NULL;
-}
-
-ImportThunk * ImportsHandling::getImportThunk(CTreeItem item)
-{
- stdext::hash_map::const_iterator it;
- TreeItemData * data = getItemData(item);
- if(data && !data->isModule)
- {
- return data->import;
- }
- return NULL;
-}
-
-void ImportsHandling::setItemData(CTreeItem item, const TreeItemData * data)
-{
- itemData[item] = *data;
-}
-
-ImportsHandling::TreeItemData * ImportsHandling::getItemData(CTreeItem item)
-{
- stdext::hash_map::iterator it;
- it = itemData.find(item);
- if(it != itemData.end())
- {
- return &it->second;
- }
- return NULL;
}
void ImportsHandling::updateCounts()
@@ -144,160 +85,17 @@ void ImportsHandling::updateCounts()
}
}
-/*bool ImportsHandling::addImport(const CHAR * moduleName, const CHAR * name, DWORD_PTR va, DWORD_PTR rva, WORD ordinal, bool valid, bool suspect)
-{
- ImportThunk import;
- ImportModuleThunk * module = 0;
- std::map::iterator iterator1;
-
- if (moduleList.size() > 1)
- {
- iterator1 = moduleList.begin();
- while (iterator1 != moduleList.end())
- {
- if (rva >= iterator1->second.firstThunk)
- {
- iterator1++;
- if (iterator1 == moduleList.end())
- {
- iterator1--;
- module = &(iterator1->second);
- break;
- }
- else if (rva < iterator1->second.firstThunk)
- {
- iterator1--;
- module = &(iterator1->second);
- break;
- }
- }
- }
- }
- else
- {
- iterator1 = moduleList.begin();
- module = &(iterator1->second);
- }
-
- if (!module)
- {
- DoOutputDebugString("ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL, rva);
- return false;
- }
-
- //TODO
- import.suspect = true;
- import.valid = false;
- import.va = va;
- import.rva = rva;
- import.ordinal = ordinal;
-
- strcpy_s(import.moduleName, MAX_PATH, moduleName);
- strcpy_s(import.name, MAX_PATH, name);
-
- module->thunkList.insert(std::pair(import.rva, import));
-
- return true;
-}
-*/
-
-/*
-bool ImportsHandling::addModule(const CHAR * moduleName, DWORD_PTR firstThunk)
-{
- ImportModuleThunk module;
-
- module.firstThunk = firstThunk;
- strcpy_s(module.moduleName, MAX_PATH, moduleName);
-
- moduleList.insert(std::pair(firstThunk,module));
-
- return true;
-}
-
-void ImportsHandling::displayAllImports()
-{
- std::map::iterator it_module;
- std::map::iterator it_import;
-
- //TreeImports.DeleteAllItems();
- itemData.clear();
- //TreeImports.SetImageList(TreeIcons);
-
- it_module = moduleList.begin();
- while (it_module != moduleList.end())
- {
- ImportModuleThunk &moduleThunk = it_module->second;
-
- moduleThunk.key = moduleThunk.firstThunk; // This belongs elsewhere...
- //moduleThunk.hTreeItem = addDllToTreeView(TreeImports, &moduleThunk);
-
- it_import = moduleThunk.thunkList.begin();
- while (it_import != moduleThunk.thunkList.end())
- {
- ImportThunk &importThunk = it_import->second;
-
- importThunk.key = importThunk.rva; // This belongs elsewhere...
- importThunk.hTreeItem = addApiToTreeView(TreeImports, moduleThunk.hTreeItem, &importThunk);
-
- it_import++;
- }
-
- it_module++;
- }
-
- updateCounts();
-}
-*/
-
void ImportsHandling::clearAllImports()
{
- //TreeImports.DeleteAllItems();
- itemData.clear();
moduleList.clear();
updateCounts();
}
-/*
-CTreeItem ImportsHandling::addDllToTreeView(CMultiSelectTreeViewCtrl& idTreeView, ImportModuleThunk * moduleThunk)
-{
- CTreeItem item = idTreeView.InsertItem("", NULL, TVI_ROOT);
-
- item.SetData(itemData.size());
-
- TreeItemData data;
- data.isModule = true;
- data.module = moduleThunk;
-
- setItemData(item, &data);
-
- updateModuleInTreeView(moduleThunk, item);
- return item;
-}
-
-CTreeItem ImportsHandling::addApiToTreeView(CMultiSelectTreeViewCtrl& idTreeView, CTreeItem parentDll, ImportThunk * importThunk)
-{
- CTreeItem item = idTreeView.InsertItem("", parentDll, TVI_LAST);
-
- item.SetData(itemData.size());
-
- TreeItemData data;
- data.isModule = false;
- data.import = importThunk;
-
- setItemData(item, &data);
-
- updateImportInTreeView(importThunk, item);
- return item;
-}
-*/
-
void ImportsHandling::selectImports(bool invalid, bool suspect)
{
std::map::iterator it_module;
std::map::iterator it_import;
- //TreeImports.SelectAllItems(FALSE); //remove selection
-
it_module = moduleList.begin();
while (it_module != moduleList.end())
{
@@ -307,13 +105,6 @@ void ImportsHandling::selectImports(bool invalid, bool suspect)
while (it_import != moduleThunk.thunkList.end())
{
ImportThunk &importThunk = it_import->second;
-
- if ((invalid && !importThunk.valid) || (suspect && importThunk.suspect))
- {
- //TreeImports.SelectItem(importThunk.hTreeItem, TRUE);
- importThunk.hTreeItem.EnsureVisible();
- }
-
it_import++;
}
@@ -321,232 +112,6 @@ void ImportsHandling::selectImports(bool invalid, bool suspect)
}
}
-bool ImportsHandling::invalidateImport(CTreeItem item)
-{
- ImportThunk * import = getImportThunk(item);
- if(import)
- {
- CTreeItem parent = item.GetParent();
- if(!parent.IsNull())
- {
- const ImportModuleThunk * module = getModuleThunk(parent);
- if(module)
- {
- import->invalidate();
-
- updateImportInTreeView(import, import->hTreeItem);
- updateModuleInTreeView(module, module->hTreeItem);
-
- updateCounts();
- return true;
- }
- }
- }
- return false;
-}
-
-bool ImportsHandling::invalidateModule(CTreeItem item)
-{
- ImportModuleThunk * module = getModuleThunk(item);
- if(module)
- {
- std::map::iterator it_import;
-
- it_import = module->thunkList.begin();
- while(it_import != module->thunkList.end())
- {
- ImportThunk * import = &it_import->second;
- import->invalidate();
- updateImportInTreeView(import, import->hTreeItem);
- it_import++;
- }
-
- updateModuleInTreeView(module, module->hTreeItem);
-
- updateCounts();
- return true;
- }
- return false;
-}
-
-bool ImportsHandling::setImport(CTreeItem item, const CHAR * moduleName, const CHAR * apiName, WORD ordinal, WORD hint, bool valid, bool suspect)
-{
- ImportThunk * import = getImportThunk(item);
- if(import)
- {
- CTreeItem parent = item.GetParent();
- if(!parent.IsNull())
- {
- ImportModuleThunk * module = getModuleThunk(parent);
- if(module)
- {
-
- strcpy_s(import->moduleName, moduleName);
- strcpy_s(import->name, apiName);
- import->ordinal = ordinal;
- //import->apiAddressVA = api->va; //??
- import->hint = hint;
- import->valid = valid;
- import->suspect = suspect;
-
- if (module->isValid())
- {
- scanAndFixModuleList();
- //displayAllImports();
- }
- else
- {
- updateImportInTreeView(import, item);
- updateCounts();
- }
- return true;
- }
- }
- }
- return false;
-}
-
-void ImportsHandling::updateImportInTreeView(const ImportThunk * importThunk, CTreeItem item)
-{
- if (importThunk->valid)
- {
- CHAR tempString[300];
-
- if (importThunk->name[0] != 0x00)
- {
- sprintf_s(tempString, "ord: %04X name: %s", importThunk->ordinal, importThunk->name);
- }
- else
- {
- sprintf_s(tempString, "ord: %04X", importThunk->ordinal);
- }
-
- sprintf_s(stringBuffer, " rva: " PRINTF_DWORD_PTR_HALF " mod: %s %s", importThunk->rva, importThunk->moduleName, tempString);
- }
- else
- {
- sprintf_s(stringBuffer, " rva: " PRINTF_DWORD_PTR_HALF " ptr: " PRINTF_DWORD_PTR_FULL, importThunk->rva, importThunk->apiAddressVA);
- }
-
-// item.SetText(stringBuffer);
-// Icon icon = getAppropiateIcon(importThunk);
-// item.SetImage(icon, icon);
-}
-
-void ImportsHandling::updateModuleInTreeView(const ImportModuleThunk * importThunk, CTreeItem item)
-{
- sprintf_s(stringBuffer, "%s (%d) FThunk: " PRINTF_DWORD_PTR_HALF, importThunk->moduleName,importThunk->thunkList.size(), importThunk->firstThunk);
-
- item.SetText(stringBuffer);
- Icon icon = getAppropiateIcon(importThunk->isValid());
- item.SetImage(icon, icon);
-}
-
-ImportsHandling::Icon ImportsHandling::getAppropiateIcon(const ImportThunk * importThunk)
-{
- if(importThunk->valid)
- {
- if(importThunk->suspect)
- {
- return iconWarning;
- }
- else
- {
- return iconCheck;
- }
- }
- else
- {
- return iconError;
- }
-}
-
-ImportsHandling::Icon ImportsHandling::getAppropiateIcon(bool valid)
-{
- if(valid)
- {
- return iconCheck;
- }
- else
- {
- return iconError;
- }
-}
-
-bool ImportsHandling::cutImport(CTreeItem item)
-{
- ImportThunk * import = getImportThunk(item);
- if(import)
- {
- CTreeItem parent = item.GetParent();
- if(!parent.IsNull())
- {
- ImportModuleThunk * module = getModuleThunk(parent);
- if(module)
- {
- itemData.erase(item);
- import->hTreeItem.Delete();
- module->thunkList.erase(import->key);
- import = 0;
-
- if (module->thunkList.empty())
- {
- itemData.erase(parent);
- module->hTreeItem.Delete();
- moduleList.erase(module->key);
- module = 0;
- }
- else
- {
- if (module->isValid() && module->moduleName[0] == L'?')
- {
- //update module name
- strcpy_s(module->moduleName, module->thunkList.begin()->second.moduleName);
- }
-
- module->firstThunk = module->thunkList.begin()->second.rva;
- updateModuleInTreeView(module, module->hTreeItem);
- }
-
- updateCounts();
- return true;
- }
- }
- }
- return false;
-}
-
-bool ImportsHandling::cutModule(CTreeItem item)
-{
- ImportModuleThunk * module = getModuleThunk(item);
- if(module)
- {
- CTreeItem child = item.GetChild();
- while(!child.IsNull())
- {
- itemData.erase(child);
- child = child.GetNextSibling();
- }
- itemData.erase(item);
- module->hTreeItem.Delete();
- moduleList.erase(module->key);
- module = 0;
- updateCounts();
- return true;
- }
- return false;
-}
-
-DWORD_PTR ImportsHandling::getApiAddressByNode(CTreeItem item)
-{
- const ImportThunk * import = getImportThunk(item);
- if(import)
- {
- return import->apiAddressVA;
- }
- return 0;
-}
-
void ImportsHandling::scanAndFixModuleList()
{
CHAR prevModuleName[MAX_PATH] = {0};
@@ -787,29 +352,3 @@ bool ImportsHandling::addFunctionToModuleList(const ImportThunk * apiFound)
module->thunkList[import.key] = import;
return true;
}
-
-void ImportsHandling::expandAllTreeNodes()
-{
- changeExpandStateOfTreeNodes(TVE_EXPAND);
-}
-
-void ImportsHandling::collapseAllTreeNodes()
-{
- changeExpandStateOfTreeNodes(TVE_COLLAPSE);
-}
-
-void ImportsHandling::changeExpandStateOfTreeNodes(UINT flag)
-{
- std::map::iterator it_module;
-
- it_module = moduleList.begin();
- while (it_module != moduleList.end())
- {
- ImportModuleThunk &moduleThunk = it_module->second;
-
- moduleThunk.hTreeItem.Expand(flag);
-
- it_module++;
- }
-}
-
diff --git a/CAPE/Scylla/ImportsHandling.h b/CAPE/Scylla/ImportsHandling.h
index 8a7fcb4..3c1ee9b 100644
--- a/CAPE/Scylla/ImportsHandling.h
+++ b/CAPE/Scylla/ImportsHandling.h
@@ -1,15 +1,9 @@
#pragma once
+#include
#include