diff --git a/.gitignore b/.gitignore
index 4a48ed0..418e99b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,5 @@ Release
tests/logging-test.*
*.suo
*.opendb
+*.VC.db
+.vs/*
diff --git a/CAPE/CAPE.c b/CAPE/CAPE.c
index abfa75b..d242730 100644
--- a/CAPE/CAPE.c
+++ b/CAPE/CAPE.c
@@ -21,9 +21,14 @@ along with this program.If not, see .
#include
#include
#include
+#include
+#include
+#include
+#include
#include "CAPE.h"
#include "Debugger.h"
+#include "..\alloc.h"
#include "..\pipe.h"
#include "..\config.h"
@@ -31,18 +36,34 @@ along with this program.If not, see .
#define BUFSIZE 1024 // For hashing
#define MD5LEN 16
+#define DUMP_MAX 100
+#define CAPE_OUTPUT_FILE "CapeOutput.bin"
+
+static unsigned int DumpCount;
+
+extern uint32_t path_from_handle(HANDLE handle, wchar_t *path, uint32_t path_buffer_len);
+
+#define CAPE_OUTPUT_FILE "CapeOutput.bin"
extern void DoOutputDebugString(_In_ LPCTSTR lpOutputString, ...);
extern void DoOutputErrorString(_In_ LPCTSTR lpOutputString, ...);
extern void CapeOutputFile(LPCTSTR lpOutputFile);
+extern int IsPeImageVirtual(DWORD_PTR Buffer);
extern int ScyllaDumpCurrentProcess(DWORD NewOEP);
extern int ScyllaDumpProcess(HANDLE hProcess, DWORD_PTR modBase, DWORD NewOEP);
extern int ScyllaDumpCurrentProcessFixImports(DWORD NewOEP);
+extern int ScyllaDumpProcessFixImports(HANDLE hProcess, DWORD_PTR modBase, DWORD NewOEP);
+extern void ExtractionClearAll(void);
+
+extern wchar_t *our_process_path;
+extern ULONG_PTR base_of_dll_of_interest;
static HMODULE s_hInst = NULL;
static WCHAR s_wzDllPath[MAX_PATH];
CHAR s_szDllPath[MAX_PATH];
+BOOL ProcessDumped;
+
//**************************************************************************************
void PrintHexBytes(__in char* TextBuffer, __in BYTE* HexBuffer, __in unsigned int Count)
//**************************************************************************************
@@ -60,6 +81,117 @@ void PrintHexBytes(__in char* TextBuffer, __in BYTE* HexBuffer, __in unsigned in
return;
}
+//*********************************************************************************************************************************
+BOOL TranslatePathFromDeviceToLetter(__in char *DeviceFilePath, __out char* DriveLetterFilePath, __inout LPDWORD lpdwBufferSize)
+//*********************************************************************************************************************************
+{
+ char DriveStrings[BUFSIZE];
+ DriveStrings[0] = '\0';
+
+ if (DriveLetterFilePath == NULL || *lpdwBufferSize < MAX_PATH)
+ {
+ *lpdwBufferSize = MAX_PATH;
+ return FALSE;
+ }
+
+ if (GetLogicalDriveStrings(BUFSIZE-1, DriveStrings))
+ {
+ char DeviceName[MAX_PATH];
+ char szDrive[3] = " :";
+ BOOL FoundDevice = FALSE;
+ char* p = DriveStrings;
+
+ do
+ {
+ *szDrive = *p;
+
+ if (QueryDosDevice(szDrive, DeviceName, MAX_PATH))
+ {
+ size_t DeviceNameLength = strlen(DeviceName);
+
+ if (DeviceNameLength < MAX_PATH)
+ {
+ FoundDevice = _strnicmp(DeviceFilePath, DeviceName, DeviceNameLength) == 0;
+
+ if (FoundDevice && *(DeviceFilePath + DeviceNameLength) == ('\\'))
+ {
+ // Construct DriveLetterFilePath replacing device path with DOS path
+ char NewPath[MAX_PATH];
+ StringCchPrintf(NewPath, MAX_PATH, TEXT("%s%s"), szDrive, DeviceFilePath+DeviceNameLength);
+ StringCchCopyN(DriveLetterFilePath, MAX_PATH, NewPath, strlen(NewPath));
+ }
+ }
+ }
+
+ // Go to the next NULL character.
+ while (*p++);
+ }
+ while (!FoundDevice && *p); // end of string
+ }
+ else
+ {
+ DoOutputErrorString("TranslatePathFromDeviceToLetter: GetLogicalDriveStrings failed");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL SetCapeMetaData(DWORD DumpType, DWORD TargetPid, HANDLE hTargetProcess, PVOID Address)
+//**************************************************************************************
+{
+ if (DumpType == 0)
+ {
+ DoOutputDebugString("SetCapeMetaData: DumpType NULL.\n");
+ return FALSE;
+ }
+
+ CapeMetaData->DumpType = DumpType;
+
+ if (DumpType == INJECTION_PE || DumpType == INJECTION_SHELLCODE)
+ {
+ if (!TargetPid)
+ {
+ DoOutputDebugString("SetCapeMetaData: Injection type with no PID - error.\n");
+ return FALSE;
+ }
+
+ if (!hTargetProcess)
+ {
+ DoOutputDebugString("SetCapeMetaData: Injection type with no process handle - error.\n");
+ return FALSE;
+ }
+
+ CapeMetaData->TargetPid = 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);
+ DoOutputErrorString("SetCapeMetaData: GetModuleFileNameEx failed on target process, handle 0x%x", hTargetProcess);
+ return FALSE;
+ }
+ }
+ else if (DumpType == EXTRACTION_PE || DumpType == EXTRACTION_SHELLCODE)
+ {
+ if (!Address)
+ {
+ DoOutputDebugString("SetCapeMetaData: Extraction type with no PID - error.\n");
+ return FALSE;
+ }
+
+ CapeMetaData->Address = Address;
+ }
+
+ return TRUE;
+}
+
//**************************************************************************************
BOOL MapFile(HANDLE hFile, unsigned char **Buffer, DWORD* FileSize)
//**************************************************************************************
@@ -69,7 +201,7 @@ BOOL MapFile(HANDLE hFile, unsigned char **Buffer, DWORD* FileSize)
if (!GetFileSizeEx(hFile, &LargeFileSize))
{
- DoOutputErrorString("Cannot get file size");
+ DoOutputErrorString("MapFile: Cannot get file size");
return FALSE;
}
@@ -79,6 +211,12 @@ BOOL MapFile(HANDLE hFile, unsigned char **Buffer, DWORD* FileSize)
return FALSE;
}
+ if (LargeFileSize.LowPart == 0)
+ {
+ DoOutputDebugString("MapFile: File is zero in size.");
+ return FALSE;
+ }
+
*FileSize = LargeFileSize.LowPart;
DoOutputDebugString("File size: 0x%x", *FileSize);
@@ -106,7 +244,7 @@ BOOL MapFile(HANDLE hFile, unsigned char **Buffer, DWORD* FileSize)
if (dwBytesRead > 0 && dwBytesRead < *FileSize)
{
- DoOutputErrorString("MapFile: Unexpected size read in.");
+ DoOutputErrorString("MapFile: Unexpected size read in");
free(Buffer);
return FALSE;
@@ -121,6 +259,353 @@ BOOL MapFile(HANDLE hFile, unsigned char **Buffer, DWORD* FileSize)
return TRUE;
}
+//**************************************************************************************
+PINJECTIONINFO GetInjectionInfo(DWORD ProcessId)
+//**************************************************************************************
+{
+ DWORD CurrentProcessId;
+
+ PINJECTIONINFO CurrentInjectionInfo = InjectionInfoList;
+ while (CurrentInjectionInfo)
+ {
+ CurrentProcessId = CurrentInjectionInfo->ProcessId;
+
+ if (CurrentProcessId == ProcessId)
+ return CurrentInjectionInfo;
+ else
+ CurrentInjectionInfo = CurrentInjectionInfo->NextInjectionInfo;
+ }
+
+ return NULL;
+}
+
+//**************************************************************************************
+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;
+
+ 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;
+}
+
+//**************************************************************************************
+PINJECTIONSECTIONVIEW GetSectionView(HANDLE SectionHandle)
+//**************************************************************************************
+{
+ PINJECTIONSECTIONVIEW CurrentSectionView = SectionViewList;
+
+ //TODO remove debug
+ DoOutputDebugString("GetSectionView: Global section view list 0x%x, looking for handle 0x%x\n", CurrentSectionView, SectionHandle);
+
+ while (CurrentSectionView)
+ {
+ //TODO remove debug
+ DoOutputDebugString("GetSectionView: looking at section handle 0x%x.\n", CurrentSectionView->SectionHandle);
+ if (CurrentSectionView->SectionHandle == SectionHandle)
+ {
+ DoOutputDebugString("GetSectionView: returning section view pointer 0x%x.\n", CurrentSectionView);
+ return CurrentSectionView;
+ }
+
+ CurrentSectionView = CurrentSectionView->NextSectionView;
+ }
+
+ return NULL;
+}
+
+//**************************************************************************************
+PINJECTIONSECTIONVIEW AddSectionView(HANDLE SectionHandle, PVOID LocalView, SIZE_T ViewSize)
+//**************************************************************************************
+{
+ 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;
+
+ 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;
+ }
+
+ return CurrentSectionView;
+}
+
+//**************************************************************************************
+BOOL DropSectionView(PINJECTIONSECTIONVIEW SectionView)
+//**************************************************************************************
+{
+ PINJECTIONSECTIONVIEW CurrentSectionView, PreviousSectionView;
+
+ PreviousSectionView = NULL;
+
+ if (SectionViewList == NULL)
+ {
+ DoOutputDebugString("DropSectionView: failed to obtain initial section view list.\n");
+ return FALSE;
+ }
+
+ CurrentSectionView = SectionViewList;
+
+ while (CurrentSectionView)
+ {
+ if (CurrentSectionView == SectionView)
+ {
+ // Unlink this from the list and free the memory
+ if (PreviousSectionView && CurrentSectionView->NextSectionView)
+ {
+ PreviousSectionView->NextSectionView = CurrentSectionView->NextSectionView;
+ DoOutputDebugString("DropSectionView: removed a view from section view list.\n");
+ }
+ else if (PreviousSectionView && CurrentSectionView->NextSectionView == NULL)
+ {
+ PreviousSectionView->NextSectionView = NULL;
+ DoOutputDebugString("DropSectionView: removed the view from the end of the section view list.\n");
+ }
+ else if (!PreviousSectionView)
+ {
+ SectionViewList = NULL;
+ DoOutputDebugString("DropSectionView: removed the head of the section view list.\n");
+ }
+
+ free(CurrentSectionView);
+
+ return TRUE;
+ }
+
+ PreviousSectionView = CurrentSectionView;
+ CurrentSectionView = CurrentSectionView->NextSectionView;
+ }
+
+ return FALSE;
+}
+
+//**************************************************************************************
+void DumpSectionViewsForPid(DWORD Pid)
+//**************************************************************************************
+{
+ struct InjectionInfo *CurrentInjectionInfo;
+ PINJECTIONSECTIONVIEW CurrentSectionView;
+ DWORD BufferSize = MAX_PATH;
+ LPVOID PEPointer = NULL;
+ BOOL Dumped = FALSE;
+
+ CurrentInjectionInfo = GetInjectionInfo(Pid);
+
+ if (CurrentInjectionInfo == NULL)
+ {
+ DoOutputDebugString("DumpSectionViewsForPid: No injection info for pid %d.\n", Pid);
+ return;
+ }
+
+ CurrentSectionView = SectionViewList;
+
+ while (CurrentSectionView)
+ {
+ if (CurrentSectionView->TargetProcessId == Pid)
+ {
+ DoOutputDebugString("DumpSectionViewsForPid: Shared section view found with pid %d.\n", Pid);
+
+ if (CurrentSectionView->LocalView)
+ {
+ PEPointer = CurrentSectionView->LocalView;
+
+ while (ScanForPE(PEPointer, CurrentSectionView->ViewSize - ((DWORD_PTR)PEPointer - (DWORD_PTR)CurrentSectionView->LocalView), &PEPointer))
+ {
+ DoOutputDebugString("DumpSectionViewsForPid: Dumping PE image from shared section view, local address 0x%x.\n", PEPointer);
+
+ CapeMetaData->DumpType = INJECTION_PE;
+ CapeMetaData->TargetPid = Pid;
+ CapeMetaData->Address = PEPointer;
+
+ if (DumpImageInCurrentProcess((DWORD_PTR)PEPointer))
+ {
+ DoOutputDebugString("DumpSectionViewsForPid: Dumped PE image from shared section view.\n");
+ Dumped = TRUE;
+ }
+ 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.");
+ }
+ }
+ }
+
+ //DropSectionView(CurrentSectionView);
+
+ CurrentSectionView = CurrentSectionView->NextSectionView;
+ }
+
+ if (Dumped == FALSE)
+ DoOutputDebugString("DumpSectionViewsForPid: no shared section views found for pid %d.\n", Pid);
+
+ return;
+}
+
+//**************************************************************************************
+char* GetName()
+//**************************************************************************************
+{
+ char *OutputFilename, *FullPathName;
+ SYSTEMTIME Time;
+ DWORD RetVal;
+
+ FullPathName = (char*) malloc(MAX_PATH);
+
+ if (FullPathName == NULL)
+ {
+ DoOutputErrorString("GetName: Error allocating memory for full path string");
+ return 0;
+ }
+
+ OutputFilename = (char*)malloc(MAX_PATH);
+
+ if (OutputFilename == NULL)
+ {
+ DoOutputErrorString("GetName: failed to allocate memory for file name string");
+ return 0;
+ }
+
+ GetSystemTime(&Time);
+ sprintf_s(OutputFilename, MAX_PATH*sizeof(char), "%d_%d%d%d%d%d%d%d%d", GetCurrentProcessId(), 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);
+
+ if (RetVal == 0 && GetLastError() != ERROR_ALREADY_EXISTS)
+ {
+ DoOutputDebugString("GetName: Error creating output directory");
+ free(OutputFilename);
+ free(FullPathName);
+ return 0;
+ }
+
+ PathAppend(FullPathName, OutputFilename);
+
+ return FullPathName;
+}
+
//**************************************************************************************
BOOL GetHash(unsigned char* Buffer, unsigned int Size, char* OutputFilenameBuffer)
//**************************************************************************************
@@ -183,7 +668,7 @@ char* GetHashFromHandle(HANDLE hFile)
if (!MapFile(hFile, &Buffer, &FileSize))
{
- DoOutputErrorString("MapFile error - check path!");
+ DoOutputErrorString("MapFile error - check the path is valid and the file has size.");
return 0;
}
@@ -191,11 +676,15 @@ char* GetHashFromHandle(HANDLE hFile)
if (OutputFilenameBuffer == NULL)
{
- DoOutputErrorString("Error allocating memory for hash string.");
+ DoOutputErrorString("Error allocating memory for hash string");
return 0;
}
- GetHash(Buffer, FileSize, (char*)OutputFilenameBuffer);
+ if (!GetHash(Buffer, FileSize, (char*)OutputFilenameBuffer))
+ {
+ DoOutputErrorString("GetHashFromHandle: GetHash function failed");
+ return 0;
+ }
DoOutputDebugString("GetHash returned: %s", OutputFilenameBuffer);
@@ -286,7 +775,7 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
if (DecryptedBuffer == NULL)
{
- DoOutputErrorString(TEXT("Error allocating memory for decrypted PE binary."));
+ DoOutputErrorString("Error allocating memory for decrypted PE binary");
return FALSE;
}
@@ -295,10 +784,11 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
for (k=0; kAddress = DecryptedBuffer;
+ DumpImageInCurrentProcess((DWORD_PTR)DecryptedBuffer);
free(DecryptedBuffer);
- return TRUE;
+ return i;
}
else
{
@@ -307,6 +797,7 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
}
}
}
+
#ifndef _WIN64
for (i=0; i<=0xffff; i++)
{
@@ -357,7 +848,7 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
if (DecryptedBuffer == NULL)
{
- DoOutputErrorString(TEXT("Error allocating memory for decrypted PE binary."));
+ DoOutputErrorString("Error allocating memory for decrypted PE binary");
return FALSE;
}
@@ -366,7 +857,8 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
for (k=0; kAddress = DecryptedBuffer;
+ DumpImageInCurrentProcess((DWORD_PTR)DecryptedBuffer);
free(DecryptedBuffer);
return TRUE;
@@ -401,7 +893,7 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
if (DecryptedBuffer == NULL)
{
- DoOutputErrorString(TEXT("Error allocating memory for decrypted PE binary."));
+ DoOutputErrorString("Error allocating memory for decrypted PE binary");
return FALSE;
}
@@ -410,7 +902,8 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
for (k=0; kAddress = DecryptedBuffer;
+ DumpImageInCurrentProcess((DWORD_PTR)DecryptedBuffer);
free(DecryptedBuffer);
return TRUE;
@@ -457,7 +950,7 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
if (DecryptedBuffer == NULL)
{
- DoOutputErrorString(TEXT("Error allocating memory for decrypted PE binary."));
+ DoOutputErrorString("Error allocating memory for decrypted PE binary");
return FALSE;
}
@@ -466,7 +959,8 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
for (k=0; kAddress = DecryptedBuffer;
+ DumpImageInCurrentProcess((DWORD_PTR)DecryptedBuffer);
free(DecryptedBuffer);
return TRUE;
@@ -474,6 +968,7 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
}
}
}
+
#endif
// We free can free DecryptedBuffer as it's no longer needed
free(DecryptedBuffer);
@@ -482,95 +977,413 @@ int DumpXorPE(LPBYTE Buffer, unsigned int Size)
}
//**************************************************************************************
-int DumpMemory(LPCVOID Buffer, unsigned int Size)
+int ScanPageForNonZero(LPVOID Address)
//**************************************************************************************
{
- char *OutputFilename, *FullPathName;
- DWORD RetVal, dwBytesWritten;
- HANDLE hOutputFile;
+ unsigned int p;
+ DWORD_PTR AddressOfPage;
+
+ if (!SystemInfo.dwPageSize)
+ GetSystemInfo(&SystemInfo);
+
+ if (!SystemInfo.dwPageSize)
+ {
+ DoOutputErrorString("Failed to obtain system page size.\n");
+ return 0;
+ }
+
+ AddressOfPage = ((DWORD_PTR)Address/SystemInfo.dwPageSize)*SystemInfo.dwPageSize;
+
+ __try
+ {
+ for (p=0; pe_lfanew == 0)
+ {
+ // e_lfanew is zero
+ continue;
+ }
+
+ if ((ULONG)pDosHeader->e_lfanew > Size-p)
+ {
+ // e_lfanew points beyond end of region
+ continue;
+ }
+
+ pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pDosHeader + (ULONG)pDosHeader->e_lfanew);
+
+ if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
+ {
+ // No 'PE' header
+ continue;
+ }
+
+ 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)
+ {
+ DoOutputDebugString("ScanForPE: Exception occured reading memory address 0x%x\n", (DWORD_PTR)((char*)Buffer+p));
+ return 0;
+ }
+ }
- DoOutputDebugString("GetHash returned: %s", OutputFilename);
+ DoOutputDebugString("ScanForPE: No PE image located at 0x%x.\n", Buffer);
+ return 0;
+}
- sprintf_s((OutputFilename+2*MD5LEN), MAX_PATH*sizeof(char)-2*MD5LEN, ".bin");
+//**************************************************************************************
+int ScanForDisguisedPE(LPVOID Buffer, unsigned int Size, LPVOID* Offset)
+//**************************************************************************************
+{
+ unsigned int p;
+ PIMAGE_DOS_HEADER pDosHeader;
+ PIMAGE_NT_HEADERS pNtHeader;
+
+ if (Size == 0)
+ {
+ DoOutputDebugString("ScanForDisguisedPE: Error, zero size given\n");
+ return 0;
+ }
+
+ for (p=0; p < Size - 0x41; p++) // we want to stop short of the look-ahead to e_lfanew
+ {
+ __try
+ {
+ pDosHeader = (PIMAGE_DOS_HEADER)((char*)Buffer+p);
+
+ if (!pDosHeader->e_lfanew || (ULONG)pDosHeader->e_lfanew > Size-p || pDosHeader->e_lfanew > PE_HEADER_LIMIT)
+ {
+ continue;
+ }
+
+ pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pDosHeader + (ULONG)pDosHeader->e_lfanew);
+
+ if ((pNtHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (pNtHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC))
+ {
+ continue;
+ }
+
+ // Basic requirements
+ if
+ (
+ pNtHeader->FileHeader.Machine == 0 ||
+ pNtHeader->FileHeader.SizeOfOptionalHeader == 0 ||
+ pNtHeader->OptionalHeader.SizeOfHeaders == 0 ||
+ pNtHeader->OptionalHeader.FileAlignment == 0
+ )
+ {
+ DoOutputDebugString("ScanForDisguisedPE: Basic requirements failure.\n");
+ continue;
+ }
- // 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 (!(pNtHeader->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
+ {
+ DoOutputDebugString("ScanForDisguisedPE: Characteristics bad.");
+ //continue;
+ }
- if (strlen(FullPathName) + strlen("\\CAPE\\") + strlen(OutputFilename) >= MAX_PATH)
- {
- DoOutputDebugString("Error, CAPE destination path too long.");
- free(OutputFilename); free(FullPathName);
- return 0;
- }
+ if (pNtHeader->FileHeader.SizeOfOptionalHeader & (sizeof (ULONG_PTR) - 1))
+ {
+ DoOutputDebugString("ScanForDisguisedPE: SizeOfOptionalHeader bad.");
+ continue;
+ }
+
+ if (((pNtHeader->OptionalHeader.FileAlignment-1) & pNtHeader->OptionalHeader.FileAlignment) != 0)
+ {
+ DoOutputDebugString("ScanForDisguisedPE: FileAlignment invalid.");
+ continue;
+ }
+
+ if (Offset)
+ {
+ *Offset = (LPVOID)((char*)Buffer+p);
+ }
+
+ DoOutputDebugString("ScanForDisguisedPE: PE image located at: 0x%x\n", (DWORD_PTR)((char*)Buffer+p));
+
+ return 1;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DoOutputDebugString("ScanForDisguisedPE: Exception occured reading memory address 0x%x\n", (DWORD_PTR)((char*)Buffer+p));
+ return 0;
+ }
+ }
+
+ DoOutputDebugString("ScanForDisguisedPE: No PE image located in range 0x%x-0x%x.\n", Buffer, (DWORD_PTR)Buffer + Size);
+ return 0;
+}
- PathAppend(FullPathName, "CAPE");
+//**************************************************************************************
+int IsDisguisedPE(LPVOID Buffer, unsigned int Size)
+//**************************************************************************************
+{
+ PIMAGE_DOS_HEADER pDosHeader;
+ PIMAGE_NT_HEADERS pNtHeader;
+
+ if (Size == 0)
+ {
+ DoOutputDebugString("IsDisguisedPE: Error, zero size given.\n");
+ return 0;
+ }
+
+ __try
+ {
+ pDosHeader = (PIMAGE_DOS_HEADER)Buffer;
- RetVal = CreateDirectory(FullPathName, NULL);
+ if (!pDosHeader->e_lfanew || pDosHeader->e_lfanew > PE_HEADER_LIMIT)
+ {
+ //DoOutputDebugString("IsDisguisedPE: e_lfanew bad.");
+ return 0;
+ }
+
+ // more tests to establish it's PE
+ pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pDosHeader + (ULONG)pDosHeader->e_lfanew);
- if (RetVal == 0 && GetLastError() != ERROR_ALREADY_EXISTS)
- {
- DoOutputDebugString("Error creating output directory");
- free(OutputFilename); free(FullPathName);
- return 0;
- }
+ if ((pNtHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (pNtHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC))
+ {
+ DoOutputDebugString("IsDisguisedPE: OptionalHeader.Magic bad.");
+ return 0;
+ }
+
+ if ((pNtHeader->FileHeader.Machine == 0) || (pNtHeader->FileHeader.SizeOfOptionalHeader == 0 || pNtHeader->OptionalHeader.SizeOfHeaders == 0))
+ {
+ // Basic requirements
+ DoOutputDebugString("IsDisguisedPE: Basic requirements bad.\n");
+ return 0;
+ }
- PathAppend(FullPathName, OutputFilename);
-
- DoOutputDebugString("DEBUG: FullPathName = %s", FullPathName);
+ if (!(pNtHeader->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
+ {
+ DoOutputDebugString("ScanForDisguisedPE: Characteristics bad.");
+ //return 0;
+ }
+
+ if (pNtHeader->FileHeader.SizeOfOptionalHeader & (sizeof (ULONG_PTR) - 1))
+ {
+ DoOutputDebugString("ScanForDisguisedPE: SizeOfOptionalHeader bad.\n");
+ return 0;
+ }
+
+ if (((pNtHeader->OptionalHeader.FileAlignment-1) & pNtHeader->OptionalHeader.FileAlignment) != 0)
+ {
+ DoOutputDebugString("ScanForDisguisedPE: FileAlignment invalid.\n");
+ return 0;
+ }
+
+ if (pNtHeader->OptionalHeader.SectionAlignment < pNtHeader->OptionalHeader.FileAlignment)
+ {
+ DoOutputDebugString("ScanForDisguisedPE: FileAlignment greater than SectionAlignment.\n");
+ return 0;
+ }
+
+ // To pass the above tests it should now be safe to assume it's a PE image
+ return 1;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DoOutputDebugString("IsDisguisedPE: Exception occured reading region at 0x%x\n", (DWORD_PTR)(Buffer));
+ return 0;
+ }
- hOutputFile = CreateFile(FullPathName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+ DoOutputDebugString("IsDisguisedPE: No PE image located\n");
+ return 0;
+}
+
+//**************************************************************************************
+BOOL DumpPEsInRange(LPVOID Buffer, SIZE_T Size)
+//**************************************************************************************
+{
+ PBYTE PEImage;
+ PIMAGE_DOS_HEADER pDosHeader;
+
+ 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*)malloc(Size - ((DWORD_PTR)PEPointer - (DWORD_PTR)Buffer));
+ memcpy(PEImage, PEPointer, Size - ((DWORD_PTR)PEPointer - (DWORD_PTR)Buffer));
+ pDosHeader = (PIMAGE_DOS_HEADER)PEImage;
+
+ *(WORD*)PEImage = IMAGE_DOS_SIGNATURE;
+ *(DWORD*)(PEImage + pDosHeader->e_lfanew) = IMAGE_NT_SIGNATURE;
+
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, (PVOID)PEPointer);
+
+ if (DumpImageInCurrentProcess((DWORD)PEImage))
+ {
+ DoOutputDebugString("DumpPEsInRange: Dumped PE image from 0x%x.\n", PEPointer);
+ RetVal = TRUE;
+ }
+ else
+ DoOutputDebugString("DumpPEsInRange: Failed to dump PE image from 0x%x.\n", PEPointer);
+ }
+ else
+ {
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, (PVOID)PEPointer);
+
+ if (DumpImageInCurrentProcess((DWORD)PEPointer))
+ {
+ DoOutputDebugString("DumpPEsInRange: Dumped PE image from 0x%x.\n", PEPointer);
+ RetVal = TRUE;
+ }
+ else
+ DoOutputDebugString("DumpPEsInRange: Failed to dump PE image from 0x%x.\n", PEPointer);
+ }
+
+ ((BYTE*)PEPointer)++;
+ }
- DoOutputDebugString("CreateFile returned: 0x%x", hOutputFile);
+ return RetVal;
+}
+
+//**************************************************************************************
+int DumpMemory(LPVOID Buffer, unsigned int Size)
+//**************************************************************************************
+{
+ char *FullPathName;
+ DWORD dwBytesWritten;
+ HANDLE hOutputFile;
+ LPVOID BufferCopy;
+
+ 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("CAPE output filename exists already: %s", FullPathName);
- free(OutputFilename); free(FullPathName);
+ DoOutputDebugString("DumpMemory: CAPE output filename exists already: %s", FullPathName);
+ free(FullPathName);
return 0;
}
- DoOutputDebugString("Passed file_exists check");
-
if (hOutputFile == INVALID_HANDLE_VALUE)
{
- DoOutputErrorString("Could not create CAPE output file");
- free(OutputFilename); free(FullPathName);
+ DoOutputErrorString("DumpMemory: Could not create CAPE output file");
+ free(FullPathName);
return 0;
}
- DoOutputDebugString("Passed invalid_handle check");
dwBytesWritten = 0;
- DoOutputDebugString("CAPE output file succssfully created:%s", FullPathName);
+ DoOutputDebugString("DumpMemory: CAPE output file successfully created: %s", FullPathName);
- if (FALSE == WriteFile(hOutputFile, Buffer, Size, &dwBytesWritten, NULL))
+ BufferCopy = (LPVOID)((BYTE*)malloc(Size));
+
+ if (BufferCopy == NULL)
+ {
+ DoOutputDebugString("DumpMemory: Failed to allocate memory for buffer copy.\n");
+ return FALSE;
+ }
+
+ __try
+ {
+ memcpy(BufferCopy, Buffer, Size);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DoOutputDebugString("DumpMemory: Exception occured reading memory address 0x%x\n", Buffer);
+ return 0;
+ }
+
+ if (FALSE == WriteFile(hOutputFile, BufferCopy, Size, &dwBytesWritten, NULL))
{
- DoOutputDebugString("WriteFile error on CAPE output file");
- free(OutputFilename); free(FullPathName);
+ DoOutputErrorString("DumpMemory: WriteFile error on CAPE output file");
+ free(FullPathName);
+ free(BufferCopy);
return 0;
}
- DoOutputDebugString("CAPE output filename: %s", FullPathName);
-
CloseHandle(hOutputFile);
+
+ CapeMetaData->Address = Buffer;
+ CapeMetaData->Size = Size;
CapeOutputFile(FullPathName);
// We can free the filename buffers
- free(OutputFilename); free(FullPathName);
+ free(FullPathName);
+ free(BufferCopy);
+
+ ExtractionClearAll();
return 1;
}
@@ -579,8 +1392,9 @@ int DumpMemory(LPCVOID Buffer, unsigned int Size)
int DumpCurrentProcessFixImports(DWORD NewEP)
//**************************************************************************************
{
- if (ScyllaDumpCurrentProcessFixImports(NewEP))
+ if (DumpCount < DUMP_MAX && ScyllaDumpCurrentProcessFixImports(NewEP))
{
+ DumpCount++;
return 1;
}
@@ -591,8 +1405,9 @@ int DumpCurrentProcessFixImports(DWORD NewEP)
int DumpCurrentProcessNewEP(DWORD NewEP)
//**************************************************************************************
{
- if (ScyllaDumpCurrentProcess(NewEP))
+ if (DumpCount < DUMP_MAX && ScyllaDumpCurrentProcess(NewEP))
{
+ DumpCount++;
return 1;
}
@@ -603,8 +1418,9 @@ int DumpCurrentProcessNewEP(DWORD NewEP)
int DumpCurrentProcess()
//**************************************************************************************
{
- if (ScyllaDumpCurrentProcess(0))
+ if (DumpCount < DUMP_MAX && ScyllaDumpCurrentProcess(0))
{
+ DumpCount++;
return 1;
}
@@ -612,11 +1428,15 @@ int DumpCurrentProcess()
}
//**************************************************************************************
-int DumpProcess(HANDLE hProcess, DWORD_PTR ImageBase)
+int DumpModuleInCurrentProcess(DWORD_PTR ModuleBase)
//**************************************************************************************
{
- if (ScyllaDumpProcess(hProcess, ImageBase, 0))
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, (PVOID)ModuleBase);
+
+ if (DumpCount < DUMP_MAX && ScyllaDumpProcess(GetCurrentProcess(), ModuleBase, 0))
{
+ ExtractionClearAll();
+ DumpCount++;
return 1;
}
@@ -624,25 +1444,167 @@ int DumpProcess(HANDLE hProcess, DWORD_PTR ImageBase)
}
//**************************************************************************************
-int DumpPE(LPCVOID Buffer)
+int DumpImageInCurrentProcess(DWORD_PTR 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 (!pDosHeader->e_lfanew || pDosHeader->e_lfanew > PE_HEADER_LIMIT)
+ {
+ DoOutputDebugString("DumpImageInCurrentProcess: bad e_lfanew.\n");
+ return 0;
+ }
+
+ pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pDosHeader + (ULONG)pDosHeader->e_lfanew);
+
+ if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
+ {
+ // No 'PE' header
+ DoOutputDebugString("DumpImageInCurrentProcess: Invalid PE signature in header.\n");
+ 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(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(), ImageBase, 0))
+ {
+ DoOutputDebugString("DumpImageInCurrentProcess: Failed to dump PE as virtual image.\n");
+ return 0;
+ }
+
+ DumpCount++;
+ return 1;
+}
+
+//**************************************************************************************
+int DumpProcess(HANDLE hProcess, DWORD_PTR ImageBase)
//**************************************************************************************
{
- if (ScyllaDumpPE((DWORD_PTR)Buffer))
+ if (DumpCount < DUMP_MAX && ScyllaDumpProcess(hProcess, ImageBase, 0))
{
+ DumpCount++;
return 1;
}
return 0;
}
+//**************************************************************************************
+int DumpPE(LPVOID Buffer)
+//**************************************************************************************
+{
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, (PVOID)Buffer);
+
+ if (DumpCount < DUMP_MAX && ScyllaDumpPE((DWORD_PTR)Buffer))
+ {
+ ExtractionClearAll();
+ DumpCount++;
+ return 1;
+ }
+
+ return 0;
+}
+
+//**************************************************************************************
+int RoutineProcessDump()
+//**************************************************************************************
+{
+ if (g_config.procmemdump && ProcessDumped == FALSE)
+ {
+ ProcessDumped = TRUE; // this prevents a second call before the first is complete
+ if (g_config.import_reconstruction)
+ {
+ if (base_of_dll_of_interest)
+ ProcessDumped = ScyllaDumpProcessFixImports(GetCurrentProcess(), base_of_dll_of_interest, 0);
+ else
+ ProcessDumped = ScyllaDumpCurrentProcessFixImports(0);
+ }
+ else
+ {
+ if (base_of_dll_of_interest)
+ ProcessDumped = ScyllaDumpProcess(GetCurrentProcess(), base_of_dll_of_interest, 0);
+ else
+ ProcessDumped = ScyllaDumpCurrentProcess(0);
+ }
+ }
+
+ return ProcessDumped;
+}
+
void init_CAPE()
{
// 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, wcslen(our_process_path)+1, CapeMetaData->ProcessPath, MAX_PATH, NULL, NULL);
+
+ // Specific to Extraction package:
+ CapeMetaData->DumpType = EXTRACTION_PE;
+ CapeMetaData->Address = NULL;
-#ifndef _WIN64
- // Start the debugger thread if required
- //launch_debugger();
+ 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;
+
+ // Cuckoo debug output level for development (0=none, 2=max)
+ // g_config.debug = 2;
+#endif
+
+ // Start the debugger thread
+ // if required by package
+ if (DEBUGGER_ENABLED)
+ launch_debugger();
+
+#ifdef _WIN64
+ DoOutputDebugString("CAPE initialised (64-bit).\n");
+#else
+ DoOutputDebugString("CAPE initialised (32-bit).\n");
#endif
return;
diff --git a/CAPE/CAPE.h b/CAPE/CAPE.h
index 50d378b..f5dcf24 100644
--- a/CAPE/CAPE.h
+++ b/CAPE/CAPE.h
@@ -1,12 +1,41 @@
-extern HMODULE s_hInst;
-extern WCHAR s_wzDllPath[MAX_PATH];
-extern CHAR s_szDllPath[MAX_PATH];
-extern int DumpCurrentProcessNewEP(DWORD NewEP);
-extern int DumpCurrentProcess();
-extern int DumpProcess(HANDLE hProcess, DWORD_PTR ImageBase);
-extern int DumpPE(LPCVOID Buffer);
-extern int ScyllaDumpPE(DWORD_PTR Buffer);
-unsigned int DumpSize;
+//Global switch for debugger
+#define DEBUGGER_ENABLED 1
+#define GUARD_PAGES_ENABLED 0
+
+typedef struct InjectionSectionView
+{
+ HANDLE SectionHandle;
+ PVOID LocalView;
+ SIZE_T ViewSize;
+ int TargetProcessId;
+ struct InjectionSectionView *NextSectionView;
+} INJECTIONSECTIONVIEW, *PINJECTIONSECTIONVIEW;
+
+PINJECTIONSECTIONVIEW AddSectionView(HANDLE SectionHandle, PVOID LocalView, SIZE_T ViewSize);
+PINJECTIONSECTIONVIEW GetSectionView(HANDLE SectionHandle);
+BOOL DropSectionView(PINJECTIONSECTIONVIEW SectionView);
+
+typedef struct InjectionInfo
+{
+ int ProcessId;
+ HANDLE ProcessHandle;
+ DWORD_PTR ImageBase;
+ DWORD_PTR EntryPoint;
+ BOOL WriteDetected;
+ BOOL ImageDumped;
+ LPVOID BufferBase;
+ unsigned int BufferSizeOfImage;
+ HANDLE SectionHandle;
+// struct InjectionSectionView *SectionViewList;
+ struct InjectionInfo *NextInjectionInfo;
+} INJECTIONINFO, *PINJECTIONINFO;
+
+struct InjectionInfo *InjectionInfoList;
+
+PINJECTIONINFO GetInjectionInfo(DWORD ProcessId);
+PINJECTIONINFO CreateInjectionInfo(DWORD ProcessId);
+
+struct InjectionSectionView *SectionViewList;
//
// MessageId: STATUS_SUCCESS
@@ -34,3 +63,65 @@ unsigned int DumpSize;
#define DATA 0
#define EXECUTABLE 1
+#define DLL 2
+
+#define PLUGX_SIGNATURE 0x5658 // 'XV'
+#define PE_HEADER_LIMIT 0x200 // Range to look for PE header within candidate buffer
+
+typedef struct CapeMetadata
+{
+ char* ProcessPath;
+ char* ModulePath;
+ DWORD Pid;
+ DWORD DumpType;
+ char* TargetProcess; // For injection
+ DWORD TargetPid; // "
+ PVOID Address; // For shellcode/modules
+ SIZE_T Size; // "
+} CAPEMETADATA, *PCAPEMETADATA;
+
+struct CapeMetadata *CapeMetaData;
+
+BOOL SetCapeMetaData(DWORD DumpType, DWORD TargetPid, HANDLE hTargetProcess, PVOID Address);
+
+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
+};
+
+extern HMODULE s_hInst;
+extern WCHAR s_wzDllPath[MAX_PATH];
+extern CHAR s_szDllPath[MAX_PATH];
+BOOL TranslatePathFromDeviceToLetter(__in TCHAR *DeviceFilePath, __out TCHAR* DriveLetterFilePath, __inout LPDWORD lpdwBufferSize);
+int DumpMemory(LPVOID Buffer, unsigned int Size);
+BOOL DumpPEsInRange(LPVOID Buffer, SIZE_T Size);
+int DumpCurrentProcessNewEP(DWORD NewEP);
+int DumpCurrentProcess();
+int DumpProcess(HANDLE hProcess, DWORD_PTR ImageBase);
+int DumpPE(LPVOID Buffer);
+int ScyllaDumpPE(DWORD_PTR Buffer);
+int ScanForNonZero(LPVOID Buffer, unsigned int Size);
+int ScanPageForNonZero(LPVOID Address);
+int ScanForPE(LPVOID Buffer, unsigned int Size, LPVOID* Offset);
+int ScanForDisguisedPE(LPVOID Buffer, unsigned int Size, LPVOID* Offset);
+int IsDisguisedPE(LPVOID Buffer, unsigned int Size);
+int DumpImageInCurrentProcess(DWORD_PTR ImageBase);
+void DumpSectionViewsForPid(DWORD Pid);
+unsigned int DumpSize;
+SYSTEM_INFO SystemInfo;
+
+HANDLE EvilGrabRegHandle;
diff --git a/CAPE/CAPE_Extraction.c b/CAPE/CAPE_Extraction.c
new file mode 100644
index 0000000..067f827
--- /dev/null
+++ b/CAPE/CAPE_Extraction.c
@@ -0,0 +1,1307 @@
+/*
+CAPE - Config And Payload Extraction
+Copyright(C) 2015, 2016 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 "Debugger.h"
+#include "CAPE.h"
+
+#define PE_HEADER_LIMIT 0x200
+#define ESTIMATED_LOOP_DELTA 0x50
+
+extern ULONG_PTR g_our_dll_base;
+extern DWORD g_our_dll_size;
+
+extern void DoOutputDebugString(_In_ LPCTSTR lpOutputString, ...);
+extern void DoOutputErrorString(_In_ LPCTSTR lpOutputString, ...);
+
+extern unsigned int address_is_in_stack(DWORD Address);
+
+extern BOOL DumpPEsInRange(LPVOID Buffer, SIZE_T Size);
+extern int DumpMemory(LPVOID Buffer, unsigned int Size);
+extern int ScanForPE(LPVOID Buffer, unsigned int Size, LPVOID* Offset);
+extern int ScanPageForNonZero(LPVOID Address);
+
+SIZE_T AllocationSize;
+PVOID AllocationBase;
+
+PVOID *pAllocationBase;
+PSIZE_T pRegionSize;
+
+PGUARDPAGES GuardedPagesToStep;
+
+BOOL AllocationWriteDetected;
+BOOL PeImageDetected;
+BOOL AllocationDumped;
+BOOL AllocationBaseWriteBpSet;
+BOOL AllocationBaseExecBpSet;
+BOOL EntryPointExecBpSet;
+static unsigned int EPBPRegister;
+
+static DWORD_PTR BasePointer, FirstEIP, LastEIP, CurrentEIP, LastDelta, TotalDelta, DeltaMax, LoopDeltaMax;
+
+BOOL MidPageExecCallback(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo);
+BOOL SetInitialWriteBreakpoint(PVOID *Address, SIZE_T RegionSize);
+BOOL SetMidPageBreakpoint(PVOID *Address, SIZE_T Size);
+
+void ExtractionClearAll(void)
+{
+ if (AllocationBase && AllocationSize)
+ ClearBreakpointsInRange(GetCurrentThreadId(), AllocationBase, AllocationSize);
+
+ AllocationSize = 0;
+ AllocationBase = NULL;
+ CapeMetaData->Address = NULL;
+
+
+ AllocationWriteDetected = FALSE;
+ PeImageDetected = FALSE;
+ AllocationBaseExecBpSet = FALSE;
+ EntryPointExecBpSet = FALSE;
+
+ return;
+}
+
+#ifndef _WIN64
+BOOL Trace(struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ if (LastEIP)
+ {
+ CurrentEIP = ExceptionInfo->ContextRecord->Eip;
+
+ if (CurrentEIP > LastEIP)
+ {
+ LastDelta = (unsigned int)(CurrentEIP - LastEIP);
+ }
+ else
+ {
+ LastDelta = (unsigned int)(LastEIP - CurrentEIP);
+ }
+
+ if (CurrentEIP > FirstEIP)
+ {
+ TotalDelta = (unsigned int)(CurrentEIP - FirstEIP);
+
+ if ((unsigned int)(CurrentEIP - FirstEIP) > DeltaMax)
+ DeltaMax = (unsigned int)(CurrentEIP - FirstEIP);
+
+ if (LoopDeltaMax && DeltaMax > LoopDeltaMax && ExceptionInfo->ContextRecord->Ebp == BasePointer)
+ // attempt dump as writing may have ended
+ {
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, AllocationBase);
+
+ if (!AllocationDumped && DumpPEsInRange(AllocationBase, AllocationSize))
+ {
+ AllocationDumped = TRUE;
+ DoOutputDebugString("Trace: successfully dumped from loop end at 0x%x.\n", CurrentEIP);
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ return TRUE;
+ }
+ else
+ {
+ DoOutputDebugString("Trace: failed to dump PE module from loop end at 0x%x (loop delta 0x%x).\n", CurrentEIP, (unsigned int)(CurrentEIP - FirstEIP));
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ TotalDelta = (unsigned int)(FirstEIP - CurrentEIP);
+
+ if (DeltaMax && DeltaMax > LoopDeltaMax)
+ LoopDeltaMax = DeltaMax;
+ }
+
+ // attempt dump as probably not in a loop, writing may have ended
+ if (TotalDelta > ESTIMATED_LOOP_DELTA && ExceptionInfo->ContextRecord->Ebp <= BasePointer)
+ {
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, AllocationBase);
+
+ if (!AllocationDumped && DumpPEsInRange(AllocationBase, AllocationSize))
+ {
+ AllocationDumped = TRUE;
+ DoOutputDebugString("Trace: successfully dumped module 0x%x bytes after last write, EIP: 0x%x\n", TotalDelta, CurrentEIP);
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ return TRUE;
+ }
+ else
+ {
+ DoOutputDebugString("Trace: failed to dump PE module 0x%x bytes after last write, EIP: 0x%x", TotalDelta, CurrentEIP);
+ return FALSE;
+ }
+ }
+ else if (!LastDelta)
+ {
+ //DoOutputDebugString("Trace: repeating instruction at 0x%x.\n", CurrentEIP);
+ SetSingleStepMode(ExceptionInfo->ContextRecord, Trace);
+ }
+ else
+ {
+ LastEIP = CurrentEIP;
+ //DoOutputDebugString("Trace: next instruction at 0x%x.\n", CurrentEIP);
+ SetSingleStepMode(ExceptionInfo->ContextRecord, Trace);
+ }
+
+ return TRUE;
+ }
+ else
+ {
+ LastEIP = ExceptionInfo->ContextRecord->Eip;
+ BasePointer = ExceptionInfo->ContextRecord->Ebp;
+ FirstEIP = LastEIP;
+ DeltaMax = 0;
+ LoopDeltaMax = 0;
+
+ DoOutputDebugString("Entering single-step mode at 0x%x.\n", FirstEIP);
+ SetSingleStepMode(ExceptionInfo->ContextRecord, Trace);
+ return TRUE;
+ }
+}
+#endif
+
+//**************************************************************************************
+void AllocationHandler(PVOID BaseAddress, SIZE_T RegionSize, ULONG AllocationType, ULONG Protect)
+//**************************************************************************************
+{
+ MEMORY_BASIC_INFORMATION meminfo;
+ PGUARDPAGES CurrentGuardPages;
+
+ if (!DebuggerInitialised)
+ return;
+
+ if (RegionSize < EXTRACTION_MIN_SIZE)
+ return;
+
+ // Whether we limit tracking to executable regions
+ if (!(Protect & EXECUTABLE_FLAGS))
+ return;
+
+ DoOutputDebugString("NtAllocateVirtualMemory hook, BaseAddress:0x%x, RegionSize: 0x%x.\n", BaseAddress, RegionSize);
+
+ CurrentGuardPages = GuardPageList;
+
+ while (CurrentGuardPages)
+ {
+ if (!CurrentGuardPages->PagesDumped && CurrentGuardPages->ReadDetected && CurrentGuardPages->WriteDetected)
+ CurrentGuardPages->PagesDumped = DumpPEsInRange(CurrentGuardPages->BaseAddress, CurrentGuardPages->RegionSize);
+
+ if (CurrentGuardPages->PagesDumped)
+ {
+ DoOutputDebugString("NtAllocateVirtualMemory hook: PE image(s) within CAPE guarded pages detected and dumped.\n");
+ ExtractionClearAll();
+ }
+
+ CurrentGuardPages = CurrentGuardPages->NextGuardPages;
+ }
+
+ if (AllocationBase && AllocationSize && !AllocationDumped)
+ {
+ if (AllocationBaseWriteBpSet == FALSE && AllocationType & MEM_COMMIT && (BaseAddress == AllocationBase))
+ { // if memory was previously reserved but not committed
+ SetInitialWriteBreakpoint(AllocationBase, AllocationSize);
+ }
+ else
+ {
+ DoOutputDebugString("NtAllocateVirtualMemory hook: attempting CAPE dump on previous region: 0x%x.\n", AllocationBase);
+
+ memset(&meminfo, 0, sizeof(meminfo));
+
+ if (!VirtualQuery(AllocationBase, &meminfo, sizeof(meminfo)))
+ {
+ DoOutputErrorString("NtAllocateVirtualMemory hook: unable to query memory region 0x%x", AllocationBase);
+ }
+ else
+ {
+ AllocationDumped = DumpPEsInRange(meminfo.AllocationBase, meminfo.RegionSize);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("NtAllocateVirtualMemory hook: PE image(s) detected and dumped.\n");
+ ExtractionClearAll();
+ }
+ else
+ {
+ SetCapeMetaData(EXTRACTION_SHELLCODE, 0, NULL, meminfo.AllocationBase);
+
+ DoOutputDebugString("NtAllocateVirtualMemory hook: dumping memory range at 0x%x.\n", AllocationBase);
+
+ if (ScanForNonZero(meminfo.AllocationBase, meminfo.RegionSize))
+ AllocationDumped = DumpMemory(meminfo.AllocationBase, meminfo.RegionSize);
+
+ if (AllocationDumped)
+ ExtractionClearAll();
+ else
+ DoOutputDebugString("NtAllocateVirtualMemory hook: Failed to dump memory range at 0x%x.\n", AllocationBase);
+ }
+
+ if (!AllocationDumped)
+ {
+ DoOutputDebugString("NtAllocateVirtualMemory hook: Previously marked memory range at: 0x%x is empty or inaccessible.\n", AllocationBase);
+ ExtractionClearAll();
+ }
+
+ // set breakpoints on new region
+ if (AllocationType & MEM_COMMIT)
+ // Allocation committed, we set an initial write bp
+ SetInitialWriteBreakpoint(BaseAddress, RegionSize);
+ else if (AllocationType & MEM_RESERVE)
+ { // Allocation not committed, so we can't set a bp yet
+ AllocationBaseWriteBpSet = FALSE;
+ AllocationBase = BaseAddress;
+ AllocationSize = RegionSize;
+ DoOutputDebugString("NtAllocateVirtualMemory hook: Memory reserved but not committed at 0x%x.\n", AllocationBase);
+ }
+ }
+ }
+ }
+ else if (AllocationType & MEM_COMMIT)
+ // Allocation committed, we set an initial write bp
+ SetInitialWriteBreakpoint(BaseAddress, RegionSize);
+ else if (AllocationType & MEM_RESERVE)
+ { // Allocation not committed, so we can't set a bp yet
+ AllocationBaseWriteBpSet = FALSE;
+ AllocationBase = BaseAddress;
+ AllocationSize = RegionSize;
+ DoOutputDebugString("NtAllocateVirtualMemory hook: Memory reserved but not committed at 0x%x.\n", AllocationBase);
+ }
+}
+
+//**************************************************************************************
+void ProtectionHandler(PVOID Address, SIZE_T RegionSize, ULONG Protect)
+//**************************************************************************************
+{
+ MEMORY_BASIC_INFORMATION meminfo;
+ PGUARDPAGES CurrentGuardPages;
+ int Register;
+ BOOL GuardedPages = FALSE;
+
+ if (!DebuggerInitialised)
+ return;
+
+ if (RegionSize < EXTRACTION_MIN_SIZE)
+ return;
+
+ if (!(Protect & EXECUTABLE_FLAGS))
+ return;
+
+ DoOutputDebugString("ProtectionHandler: Address: 0x%x, RegionSize: 0x%x\n", Address, RegionSize);
+
+ if (!VirtualQuery(Address, &meminfo, sizeof(MEMORY_BASIC_INFORMATION)))
+ {
+ DoOutputErrorString("ProtectionHandler: unable to query memory region 0x%x", Address);
+ return;
+ }
+
+ CurrentGuardPages = GuardPageList;
+
+ while (CurrentGuardPages)
+ {
+ if (!CurrentGuardPages->PagesDumped && CurrentGuardPages->ReadDetected && CurrentGuardPages->WriteDetected)
+ CurrentGuardPages->PagesDumped = DumpPEsInRange(CurrentGuardPages->BaseAddress, CurrentGuardPages->RegionSize);
+
+ if (CurrentGuardPages->PagesDumped)
+ {
+ DoOutputDebugString("ProtectionHandler: PE image(s) within CAPE guarded pages detected and dumped.\n");
+ ExtractionClearAll();
+ }
+
+ CurrentGuardPages = CurrentGuardPages->NextGuardPages;
+ }
+
+ if (AllocationBase == 0)
+ {
+ if (Address == meminfo.BaseAddress)
+ {
+ // we check if the buffer has already been written to
+ if (ScanForNonZero(meminfo.AllocationBase, RegionSize + (BYTE*)Address - (BYTE*)meminfo.AllocationBase))
+ {
+ if (DumpPEsInRange(meminfo.AllocationBase, RegionSize + (BYTE*)Address - (BYTE*)meminfo.AllocationBase))
+ {
+ DoOutputDebugString("ProtectionHandler: PE image(s) detected and dumped.\n");
+ ExtractionClearAll();
+ }
+ else if (SetNextAvailableBreakpoint(GetCurrentThreadId(), &Register, 0, (BYTE*)Address, BP_EXEC, MidPageExecCallback))
+ {
+ AllocationBaseExecBpSet = TRUE;
+ AllocationBase = Address;
+ AllocationSize = RegionSize;
+ DoOutputDebugString("ProtectionHandler: Execution breakpoint %d set base address: 0x%x, AllocationBaseExecBpSet = %d\n", Register, Address, AllocationBaseExecBpSet);
+ }
+ else
+ {
+ DoOutputDebugString("ProtectionHandler: SetNextAvailableBreakpoint failed to set exec bp on allocation base.\n");
+ return;
+ }
+ }
+ else // looks like it's still an empty buffer
+ {
+ DoOutputDebugString("ProtectionHandler: Setting initial write breakpoint on protection address: 0x%x\n", Address);
+ SetInitialWriteBreakpoint(Address, RegionSize);
+ }
+ }
+ else
+ {
+ DoOutputDebugString("ProtectionHandler: Setting mid-page exec breakpoint on protection address: 0x%x\n", Address);
+ SetMidPageBreakpoint(Address, RegionSize);
+ }
+ }
+ else if (AllocationWriteDetected && AllocationBase && AllocationSize && !AllocationDumped)
+ {
+ DoOutputDebugString("ProtectionHandler: attempting CAPE dump on region: 0x%x.\n", AllocationBase);
+
+ AllocationDumped = DumpPEsInRange(meminfo.AllocationBase, meminfo.RegionSize);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("ProtectionHandler: PE image(s) detected and dumped.\n");
+ ExtractionClearAll();
+ }
+ else
+ {
+ SetCapeMetaData(EXTRACTION_SHELLCODE, 0, NULL, meminfo.AllocationBase);
+
+ AllocationDumped = DumpMemory(meminfo.AllocationBase, meminfo.RegionSize);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("ProtectionHandler: successfully dumped memory range at 0x%x.\n", AllocationBase);
+ ExtractionClearAll();
+ }
+ }
+
+ if (!AllocationDumped)
+ {
+ DoOutputDebugString("ProtectionHandler: Previously marked memory range at: 0x%x is empty or inaccessible.\n", AllocationBase);
+ ExtractionClearAll();
+ }
+
+ if ((DWORD_PTR)Address < (DWORD_PTR)AllocationBase || (DWORD_PTR)Address >= ((DWORD_PTR)AllocationBase + AllocationSize))
+ {
+ // we check if the buffer has already been written to
+ if (ScanForNonZero(Address, RegionSize))
+ {
+ // We want to switch our 'Allocation' pointers to this region,
+ // so let's dump anything in the previous region
+ AllocationDumped = DumpPEsInRange(meminfo.AllocationBase, meminfo.RegionSize);
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("ProtectionHandler: Found and dumped PE image(s).\n");
+ ExtractionClearAll();
+ }
+
+ // Now we set up our new breakpoint
+ if (SetNextAvailableBreakpoint(GetCurrentThreadId(), &Register, 0, (BYTE*)Address, BP_EXEC, MidPageExecCallback))
+ {
+ AllocationBaseExecBpSet = TRUE;
+ AllocationBase = Address;
+ AllocationSize = RegionSize;
+ DoOutputDebugString("ProtectionHandler: Execution breakpoint %d set base address: 0x%x, AllocationBaseExecBpSet = %d\n", Register, Address, AllocationBaseExecBpSet);
+ }
+ else
+ {
+ DoOutputDebugString("ProtectionHandler: SetNextAvailableBreakpoint failed to set exec bp on allocation base.\n");
+ return;
+ }
+ }
+ else // looks like it's still an empty buffer
+ {
+ DoOutputDebugString("ProtectionHandler: Setting initial write breakpoint on protection address: 0x%x\n", Address);
+
+ SetInitialWriteBreakpoint(Address, RegionSize);
+ }
+ }
+ }
+}
+
+//**************************************************************************************
+void FreeHandler(PVOID BaseAddress, SIZE_T RegionSize)
+//**************************************************************************************
+{
+ if (BaseAddress == AllocationBase)
+ {
+ // we check if the buffer has been written to
+ if (RegionSize && ScanForNonZero(BaseAddress, RegionSize))
+ {
+ // We want to switch our 'Allocation' pointers to this region,
+ // so let's dump anything in the previous region
+ AllocationDumped = DumpPEsInRange(BaseAddress, RegionSize);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("FreeHandler: Found and dumped PE image(s).\n");
+ ExtractionClearAll();
+ }
+ else
+ {
+ SetCapeMetaData(EXTRACTION_SHELLCODE, 0, NULL, BaseAddress);
+
+ AllocationDumped = DumpMemory(BaseAddress, RegionSize);
+
+ if (AllocationDumped)
+ DoOutputDebugString("FreeHandler: dumped executable memory range at 0x%x prior to its freeing.\n", BaseAddress);
+ else
+ DoOutputDebugString("FreeHandler: failed to dump executable memory range at 0x%x prior to its freeing.\n", BaseAddress);
+ }
+ }
+
+ DoOutputDebugString("FreeHandler: Clearing breakpoints in range 0x%x - 0x%x.\n", BaseAddress, (char*)BaseAddress + RegionSize);
+ ExtractionClearAll();
+ }
+}
+
+//**************************************************************************************
+void TerminateHandler(void)
+//**************************************************************************************
+{
+ MEMORY_BASIC_INFORMATION meminfo;
+
+ if (AllocationBase && AllocationSize && !AllocationDumped)
+ {
+ memset(&meminfo, 0, sizeof(meminfo));
+
+ if (!VirtualQuery(AllocationBase, &meminfo, sizeof(meminfo)))
+ {
+ DoOutputErrorString("TerminateHandler: unable to query memory region 0x%x", AllocationBase);
+ }
+ else
+ {
+ AllocationDumped = DumpPEsInRange(meminfo.AllocationBase, meminfo.RegionSize);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("TerminateHandler: PE image(s) detected and dumped.\n");
+ ExtractionClearAll();
+ }
+ else
+ {
+ SetCapeMetaData(EXTRACTION_SHELLCODE, 0, NULL, meminfo.AllocationBase);
+
+ AllocationDumped = DumpMemory(meminfo.AllocationBase, meminfo.RegionSize);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("TerminateHandler: successfully dumped memory range at 0x%x.\n", AllocationBase);
+ ExtractionClearAll();
+ }
+ }
+
+ if (!AllocationDumped)
+ {
+ DoOutputDebugString("TerminateHandler: Previously marked memory range at: 0x%x is empty or inaccessible.\n", AllocationBase);
+ ExtractionClearAll();
+ }
+ }
+ }
+}
+
+//**************************************************************************************
+BOOL StepOverGuardPageFault(struct _EXCEPTION_POINTERS* ExceptionInfo)
+//**************************************************************************************
+{
+ PGUARDPAGES CurrentGuardPages = GuardedPagesToStep;
+
+ if (LastEIP)
+ {
+#ifdef _WIN64
+ CurrentEIP = ExceptionInfo->ContextRecord->Rip;
+#else
+ CurrentEIP = ExceptionInfo->ContextRecord->Eip;
+#endif
+
+ if (CurrentEIP == LastEIP)
+ {
+ // We want to keep stepping until we're past the instruction
+ SetSingleStepMode(ExceptionInfo->ContextRecord, StepOverGuardPageFault);
+ return TRUE;
+ }
+ else
+ {
+ if (CurrentGuardPages == NULL)
+ {
+ DoOutputDebugString("StepOverGuardPageFault error: GuardedPagesToStep not set.\n");
+ return FALSE;
+ }
+
+ if (ReinstateGuardPages(CurrentGuardPages))
+ {
+ //DoOutputDebugString("StepOverGuardPageFault: Reinstated page guard.\n");
+ GuardedPagesToStep = NULL;
+ LastEIP = (DWORD_PTR)NULL;
+ CurrentEIP = (DWORD_PTR)NULL;
+ return TRUE;
+ }
+
+ DoOutputDebugString("StepOverGuardPageFault: Failed to reinstate page guard.\n");
+ return FALSE;
+ }
+ }
+ else
+ {
+#ifdef _WIN64
+ LastEIP = ExceptionInfo->ContextRecord->Rip;
+#else
+ LastEIP = ExceptionInfo->ContextRecord->Eip;
+#endif
+
+ if (CurrentGuardPages->LastWriteAddress)
+ {
+ if (!SystemInfo.dwPageSize)
+ GetSystemInfo(&SystemInfo);
+
+ // we want to flag writes that occur beyond the first page
+ if (ScanPageForNonZero(CurrentGuardPages->LastWriteAddress) && (DWORD_PTR)CurrentGuardPages->LastWriteAddress >= (DWORD_PTR)CurrentGuardPages->BaseAddress + SystemInfo.dwPageSize)
+ {
+ if (!CurrentGuardPages->WriteDetected)
+ {
+ DoOutputDebugString("StepOverGuardPageFault: DEBUG trigger write to 0x%x, base 0x%x, pagesize 0x%x.\n", CurrentGuardPages->LastWriteAddress, CurrentGuardPages->BaseAddress, SystemInfo.dwPageSize);
+ CurrentGuardPages->WriteDetected = TRUE;
+
+ // we only care about reads that come after writes
+ CurrentGuardPages->ReadDetected = FALSE;
+ }
+ }
+ }
+
+ SetSingleStepMode(ExceptionInfo->ContextRecord, StepOverGuardPageFault);
+ return TRUE;
+ }
+}
+
+//**************************************************************************************
+BOOL ExtractionGuardPageHandler(struct _EXCEPTION_POINTERS* ExceptionInfo)
+//**************************************************************************************
+{
+ DWORD AccessType = (DWORD)ExceptionInfo->ExceptionRecord->ExceptionInformation[0];
+ PVOID AccessAddress = (PVOID)ExceptionInfo->ExceptionRecord->ExceptionInformation[1];
+ PVOID FaultingAddress = (PVOID)ExceptionInfo->ExceptionRecord->ExceptionAddress;
+
+ PGUARDPAGES CurrentGuardPages = GetGuardPages(AccessAddress);
+
+ if (CurrentGuardPages == NULL)
+ {
+ DoOutputDebugString("ExtractionGuardPageHandler error: address 0x%x not in guarded pages.\n", AccessAddress);
+ return FALSE;
+ }
+
+ switch (AccessType)
+ {
+ case EXCEPTION_WRITE_FAULT:
+
+ //DoOutputDebugString("ExtractionGuardPageHandler: Write detected at 0x%x by 0x%x\n", AccessAddress, FaultingAddress);
+
+ CurrentGuardPages->LastWriteAddress = AccessAddress;
+
+ GuardedPagesToStep = CurrentGuardPages;
+
+ SetSingleStepMode(ExceptionInfo->ContextRecord, StepOverGuardPageFault);
+
+ break;
+
+ case EXCEPTION_READ_FAULT:
+
+ if (CurrentGuardPages->WriteDetected)
+ {
+ if (!(CurrentGuardPages->Protect & (PAGE_EXECUTE_READWRITE || PAGE_EXECUTE_READ || PAGE_EXECUTE)) && !CurrentGuardPages->PagesDumped && !CurrentGuardPages->ReadDetected)
+ {
+ DoOutputDebugString("ExtractionGuardPageHandler: Read detected after previous write at 0x%x by 0x%x\n", AccessAddress, FaultingAddress);
+
+ if (DisableGuardPages(CurrentGuardPages))
+ {
+ CurrentGuardPages->PagesDumped = DumpPEsInRange(CurrentGuardPages->BaseAddress, CurrentGuardPages->RegionSize);
+ if (CurrentGuardPages->PagesDumped)
+ DoOutputDebugString("ExtractionGuardPageHandler: PE image(s) detected and dumped.\n");
+ }
+ else
+ {
+ DoOutputDebugString("ExtractionGuardPageHandler: Failed to disable guard pages for dump.\n");
+ }
+
+ // if dumping failed (for example, because of an incomplete image)
+ // we want to re-enable guard pages so we can try again
+ //if (!CurrentGuardPages->PagesDumped)
+ //{
+ // ReinstateGuardPages(CurrentGuardPages);
+ //}
+ }
+ }
+
+ CurrentGuardPages->ReadDetected = TRUE;
+ CurrentGuardPages->LastReadBy = FaultingAddress;
+
+ break;
+
+ case EXCEPTION_EXECUTE_FAULT:
+
+ DoOutputDebugString("ExtractionGuardPageHandler: Execution detected at 0x%x by 0x%x\n", AccessAddress, FaultingAddress);
+
+ if (!(CurrentGuardPages->Protect & (PAGE_EXECUTE_READWRITE || PAGE_EXECUTE_READ || PAGE_EXECUTE)))
+ {
+ DoOutputDebugString("ExtractionGuardPageHandler: Anomaly detected - pages not marked with execute flag in guarded pages list.\n");
+ }
+
+ if (!CurrentGuardPages->PagesDumped)
+ {
+ DoOutputDebugString("ExtractionGuardPageHandler: Execution within guarded page detected, dumping.\n");
+
+ if (DisableGuardPages(CurrentGuardPages))
+ {
+ CurrentGuardPages->PagesDumped = DumpPEsInRange(CurrentGuardPages->BaseAddress, CurrentGuardPages->RegionSize);
+ if (CurrentGuardPages->PagesDumped)
+ DoOutputDebugString("ExtractionGuardPageHandler: PE image(s) detected and dumped.\n");
+ else
+ {
+ SetCapeMetaData(EXTRACTION_SHELLCODE, 0, NULL, CurrentGuardPages->BaseAddress);
+
+ CurrentGuardPages->PagesDumped = DumpMemory(CurrentGuardPages->BaseAddress, CurrentGuardPages->RegionSize);
+
+ if (CurrentGuardPages->PagesDumped)
+ DoOutputDebugString("ExtractionGuardPageHandler: shellcode detected and dumped.\n");
+ else
+ DoOutputDebugString("ExtractionGuardPageHandler: failed to dump detected shellcode.\n");
+ }
+ }
+ else
+ {
+ DoOutputDebugString("ExtractionGuardPageHandler: Failed to disable guard pages for dump.\n");
+ }
+ }
+
+ break;
+
+ default:
+ DoOutputDebugString("ExtractionGuardPageHandler: Unknown access type: 0x%x - error.\n", AccessType);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL EntryPointExecCallback(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ MEMORY_BASIC_INFORMATION meminfo;
+
+ if (pBreakpointInfo == NULL)
+ {
+ DoOutputDebugString("EntryPointExecCallback executed with pBreakpointInfo NULL.\n");
+ return FALSE;
+ }
+
+ if (pBreakpointInfo->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("EntryPointExecCallback executed with NULL thread handle.\n");
+ return FALSE;
+ }
+
+ DoOutputDebugString("EntryPointExecCallback: Breakpoint %i at Address 0x%x.\n", pBreakpointInfo->Register, pBreakpointInfo->Address);
+
+ memset(&meminfo, 0, sizeof(meminfo));
+
+ if (!VirtualQuery(pBreakpointInfo->Address, &meminfo, sizeof(meminfo)))
+ {
+ DoOutputErrorString("EntryPointExecCallback: unable to query memory region 0x%x", pBreakpointInfo->Address);
+ return FALSE;
+ }
+
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, meminfo.AllocationBase);
+
+ if (AllocationDumped == TRUE)
+ {
+ DoOutputDebugString("EntryPointExecCallback: allocation already dumped, clearing breakpoint.\n");
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ }
+ else
+ {
+ AllocationDumped = DumpPEsInRange(meminfo.AllocationBase, meminfo.RegionSize);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("EntryPointExecCallback hook: PE image(s) detected and dumped.\n");
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ }
+ else
+ {
+ DoOutputDebugString("EntryPointExecCallback: failed to dump PE module.\n");
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL EntryPointWriteCallback(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ if (pBreakpointInfo == NULL)
+ {
+ DoOutputDebugString("EntryPointWriteCallback executed with pBreakpointInfo NULL.\n");
+ return FALSE;
+ }
+
+ if (pBreakpointInfo->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("EntryPointWriteCallback executed with NULL thread handle.\n");
+ return FALSE;
+ }
+
+ DoOutputDebugString("EntryPointWriteCallback: Breakpoint %i at Address 0x%x.\n", pBreakpointInfo->Register, pBreakpointInfo->Address);
+
+ if ((DWORD_PTR)pBreakpointInfo->Address < (DWORD_PTR)AllocationBase || (DWORD_PTR)pBreakpointInfo->Address > (DWORD_PTR)AllocationBase + AllocationSize)
+ {
+ DoOutputDebugString("EntryPointWriteCallback: current AddressOfEntryPoint is not within allocated region. We assume it's only partially written and await further writes.\n");
+ return TRUE;
+ }
+
+ if (EntryPointExecBpSet == FALSE)
+ {
+ if (ContextSetNextAvailableBreakpoint(ExceptionInfo->ContextRecord, &EPBPRegister, 0, (BYTE*)AllocationBase+*(DWORD*)(pBreakpointInfo->Address), BP_EXEC, EntryPointExecCallback))
+ {
+ EntryPointExecBpSet = TRUE;
+#ifdef _WIN64
+ DoOutputDebugString("EntryPointWriteCallback: Execution bp %d set on EntryPoint 0x%x (RIP = 0x%x).\n", EPBPRegister, (BYTE*)AllocationBase+*(DWORD*)(pBreakpointInfo->Address), ExceptionInfo->ContextRecord->Rip);
+#else
+ DoOutputDebugString("EntryPointWriteCallback: Execution bp %d set on EntryPoint 0x%x (EIP = 0x%x).\n", EPBPRegister, (BYTE*)AllocationBase+*(DWORD*)(pBreakpointInfo->Address), ExceptionInfo->ContextRecord->Eip);
+#endif
+ }
+ else
+ {
+ DoOutputDebugString("EntryPointWriteCallback: ContextSetNextAvailableBreakpoint on EntryPoint 0x%x failed\n", (BYTE*)AllocationBase+*(DWORD*)(pBreakpointInfo->Address));
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (ContextSetBreakpoint(ExceptionInfo->ContextRecord, EPBPRegister, 0, (BYTE*)AllocationBase+*(DWORD*)(pBreakpointInfo->Address), BP_EXEC, EntryPointExecCallback))
+ {
+ EntryPointExecBpSet = TRUE;
+#ifdef _WIN64
+ DoOutputDebugString("EntryPointWriteCallback: Updated EntryPoint execution bp %d to 0x%x (RIP = 0x%x).\n", EPBPRegister, (BYTE*)AllocationBase+*(DWORD*)(pBreakpointInfo->Address), ExceptionInfo->ContextRecord->Rip);
+#else
+ DoOutputDebugString("EntryPointWriteCallback: Updated EntryPoint execution bp %d to 0x%x (EIP = 0x%x).\n", EPBPRegister, (BYTE*)AllocationBase+*(DWORD*)(pBreakpointInfo->Address), ExceptionInfo->ContextRecord->Eip);
+#endif
+
+ // since it looks like the writing is happening at most a word at a time, let's try and catch the end of the write for another dump attempt
+ //SetSingleStepMode(ExceptionInfo->ContextRecord, Trace);
+ }
+ else
+ {
+ DoOutputDebugString("EntryPointWriteCallback: ContextSetBreakpoint on updated EntryPoint 0x%x failed\n", (BYTE*)AllocationBase+*(DWORD*)(pBreakpointInfo->Address));
+ return FALSE;
+ }
+ }
+
+ DoOutputDebugString("EntryPointWriteCallback executed successfully.\n");
+
+ return TRUE;
+}
+
+BOOL PEHeaderWriteCallback(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+#ifdef _WIN64
+ PIMAGE_NT_HEADERS64 pNtHeader;
+#else
+ PIMAGE_NT_HEADERS32 pNtHeader;
+#endif
+ if (pBreakpointInfo == NULL)
+ {
+ DoOutputDebugString("PEHeaderWriteCallback executed with pBreakpointInfo NULL.\n");
+ return FALSE;
+ }
+
+ if (pBreakpointInfo->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("PEHeaderWriteCallback executed with NULL thread handle.\n");
+ return FALSE;
+ }
+
+ DoOutputDebugString("PEHeaderWriteCallback: Breakpoint %i at Address 0x%x.\n", pBreakpointInfo->Register, pBreakpointInfo->Address);
+
+ pNtHeader = (PIMAGE_NT_HEADERS)pBreakpointInfo->Address;
+
+ if (*(DWORD*)pNtHeader == IMAGE_NT_SIGNATURE)
+ {
+ PeImageDetected = TRUE;
+
+ if (pNtHeader->OptionalHeader.AddressOfEntryPoint && pNtHeader->OptionalHeader.AddressOfEntryPoint < AllocationSize)
+ {
+ if (ContextUpdateCurrentBreakpoint(ExceptionInfo->ContextRecord, 0, (BYTE*)AllocationBase+pNtHeader->OptionalHeader.AddressOfEntryPoint, BP_EXEC, EntryPointExecCallback))
+ {
+#ifdef _WIN64
+ DoOutputDebugString("PEHeaderWriteCallback: Execution bp set on EntryPoint 0x%x (RIP = 0x%x).\n", (DWORD_PTR)AllocationBase+pNtHeader->OptionalHeader.AddressOfEntryPoint, ExceptionInfo->ContextRecord->Rip);
+#else
+ DoOutputDebugString("PEHeaderWriteCallback: Execution bp set on EntryPoint 0x%x (EIP = 0x%x).\n", (DWORD_PTR)AllocationBase+pNtHeader->OptionalHeader.AddressOfEntryPoint, ExceptionInfo->ContextRecord->Eip);
+#endif
+ }
+ else
+ {
+ DoOutputDebugString("PEHeaderWriteCallback: ContextUpdateCurrentBreakpoint failed\n");
+ ContextClearBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo);
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (ContextUpdateCurrentBreakpoint(ExceptionInfo->ContextRecord, sizeof(DWORD), (BYTE*)&(pNtHeader->OptionalHeader.AddressOfEntryPoint), BP_WRITE, EntryPointWriteCallback))
+ {
+#ifdef _WIN64
+ DoOutputDebugString("PEHeaderWriteCallback: set write bp on AddressOfEntryPoint location (RIP = 0x%x).\n", ExceptionInfo->ContextRecord->Rip);
+#else
+ DoOutputDebugString("PEHeaderWriteCallback: set write bp on AddressOfEntryPoint location (EIP = 0x%x).\n", ExceptionInfo->ContextRecord->Eip);
+#endif
+ }
+ else
+ {
+ DoOutputDebugString("PEHeaderWriteCallback: ContextUpdateCurrentBreakpoint failed\n");
+ ContextClearBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo);
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ DoOutputDebugString("PEHeaderWriteCallback: PE header has: 0x%x.\n", *(DWORD*)pNtHeader);
+ }
+
+ DoOutputDebugString("PEHeaderWriteCallback executed successfully.\n");
+
+ return TRUE;
+}
+
+BOOL PEPointerWriteCallback(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ long e_lfanew;
+
+ DoOutputDebugString("PEPointerWriteCallback entry.\n");
+
+ if (pBreakpointInfo == NULL)
+ {
+ DoOutputDebugString("PEPointerWriteCallback executed with pBreakpointInfo NULL.\n");
+ return FALSE;
+ }
+
+ if (pBreakpointInfo->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("PEPointerWriteCallback executed with NULL thread handle.\n");
+ return FALSE;
+ }
+
+ DoOutputDebugString("PEPointerWriteCallback: Breakpoint %i at Address 0x%x.\n", pBreakpointInfo->Register, pBreakpointInfo->Address);
+
+ e_lfanew = *(long*)((pBreakpointInfo->Address));
+
+ if ((unsigned int)e_lfanew > PE_HEADER_LIMIT)
+ {
+ DoOutputDebugString("PEPointerWriteCallback: pointer to PE header too big: 0x%x (perhaps writing incomplete).\n", e_lfanew);
+ return FALSE;
+ }
+
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, AllocationBase);
+
+ if (e_lfanew && (*(DWORD*)((unsigned char*)AllocationBase+e_lfanew) == IMAGE_NT_SIGNATURE))
+ {
+ if (DumpPEsInRange(AllocationBase, AllocationSize))
+ {
+ AllocationDumped = TRUE;
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ DoOutputDebugString("PEPointerWriteCallback: successfully dumped module.\n");
+ return TRUE;
+ }
+ else
+ {
+ DoOutputDebugString("PEPointerWriteCallback: failed to dump PE module.\n");
+ }
+ }
+
+ if (ContextUpdateCurrentBreakpoint(ExceptionInfo->ContextRecord, sizeof(DWORD), (BYTE*)AllocationBase+e_lfanew, BP_WRITE, PEHeaderWriteCallback))
+ {
+#ifdef _WIN64
+ DoOutputDebugString("PEPointerWriteCallback: set write bp on e_lfanew write location 0x%x (RIP = 0x%x)\n", (BYTE*)AllocationBase + e_lfanew, ExceptionInfo->ContextRecord->Rip);
+#else
+ DoOutputDebugString("PEPointerWriteCallback: set write bp on e_lfanew write location 0x%x (EIP = 0x%x)\n", (BYTE*)AllocationBase + e_lfanew, ExceptionInfo->ContextRecord->Eip);
+#endif
+ }
+ else
+ {
+ DoOutputDebugString("PEPointerWriteCallback: ContextUpdateCurrentBreakpoint failed\n");
+ return FALSE;
+ }
+
+ DoOutputDebugString("PEPointerWriteCallback executed successfully.\n");
+
+ return TRUE;
+}
+
+BOOL MidPageExecCallback(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ MEMORY_BASIC_INFORMATION meminfo;
+ SIZE_T Size;
+
+ if (pBreakpointInfo == NULL)
+ {
+ DoOutputDebugString("MidPageExecCallback executed with pBreakpointInfo NULL.\n");
+ return FALSE;
+ }
+
+ if (pBreakpointInfo->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("MidPageExecCallback executed with NULL thread handle.\n");
+ return FALSE;
+ }
+
+ DoOutputDebugString("MidPageExecCallback: Breakpoint %i at Address 0x%x.\n", pBreakpointInfo->Register, pBreakpointInfo->Address);
+
+ memset(&meminfo, 0, sizeof(meminfo));
+
+ if (!VirtualQuery(pBreakpointInfo->Address, &meminfo, sizeof(meminfo)))
+ {
+ DoOutputErrorString("MidPageExecCallback: unable to query memory region 0x%x", pBreakpointInfo->Address);
+ return FALSE;
+ }
+
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, meminfo.AllocationBase);
+
+ if ((BYTE*)AllocationBase + AllocationSize > (BYTE*)meminfo.AllocationBase && meminfo.RegionSize)
+ {
+ Size = (BYTE*)AllocationBase + AllocationSize - (BYTE*)meminfo.AllocationBase;
+ }
+ else
+ {
+ Size = AllocationSize;
+ }
+
+ if (!address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address) && (DWORD_PTR)meminfo.BaseAddress > (DWORD_PTR)meminfo.AllocationBase)
+ {
+ DoOutputDebugString("MidPageExecCallback: Debug: About to scan region for a PE image (base 0x%x, size 0x%x).\n", meminfo.AllocationBase, Size);
+ AllocationDumped = DumpPEsInRange(meminfo.AllocationBase, Size);
+ }
+ else if (address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address) || (DWORD_PTR)meminfo.BaseAddress == (DWORD_PTR)meminfo.AllocationBase)
+ {
+ DoOutputDebugString("MidPageExecCallback: Debug: About to scan region for a PE image (base 0x%x, size 0x%x).\n", meminfo.BaseAddress, meminfo.RegionSize);
+ AllocationDumped = DumpPEsInRange(meminfo.BaseAddress, meminfo.RegionSize);
+ }
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("MidPageExecCallback: PE image(s) detected and dumped.\n");
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ }
+ else
+ {
+ if (!address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address) && (DWORD_PTR)meminfo.BaseAddress > (DWORD_PTR)meminfo.AllocationBase)
+ {
+ SetCapeMetaData(EXTRACTION_SHELLCODE, 0, NULL, meminfo.AllocationBase);
+
+ AllocationDumped = DumpMemory(meminfo.AllocationBase, Size);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("MidPageExecCallback: successfully dumped memory range at 0x%x.\n", meminfo.AllocationBase);
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ }
+ }
+ else if (address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address) || (DWORD_PTR)meminfo.BaseAddress == (DWORD_PTR)meminfo.AllocationBase)
+ {
+ SetCapeMetaData(EXTRACTION_SHELLCODE, 0, NULL, meminfo.BaseAddress);
+
+ if (ScanForNonZero(meminfo.BaseAddress, Size))
+ AllocationDumped = DumpMemory(meminfo.BaseAddress, meminfo.RegionSize);
+ else
+ DoOutputDebugString("MidPageExecCallback: memory range at 0x%x is empty.\n", meminfo.BaseAddress);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("MidPageExecCallback: successfully dumped memory range at 0x%x.\n", meminfo.BaseAddress);
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ }
+ }
+ }
+
+ if (!AllocationDumped)
+ {
+ DoOutputDebugString("MidPageExecCallback: failed to dump memory range at 0x%x.\n", AllocationBase);
+ ExtractionClearAll();
+ }
+
+ DoOutputDebugString("MidPageExecCallback executed successfully.\n");
+
+ return TRUE;
+}
+
+BOOL ShellcodeExecCallback(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ MEMORY_BASIC_INFORMATION meminfo;
+ //LPVOID PEPointer;
+
+ if (pBreakpointInfo == NULL)
+ {
+ DoOutputDebugString("ShellcodeExecCallback executed with pBreakpointInfo NULL.\n");
+ return FALSE;
+ }
+
+ if (pBreakpointInfo->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("ShellcodeExecCallback executed with NULL thread handle.\n");
+ return FALSE;
+ }
+
+ DoOutputDebugString("ShellcodeExecCallback: Breakpoint %i at Address 0x%x.\n", pBreakpointInfo->Register, pBreakpointInfo->Address);
+
+ memset(&meminfo, 0, sizeof(meminfo));
+
+ if (!VirtualQuery(pBreakpointInfo->Address, &meminfo, sizeof(meminfo)))
+ {
+ DoOutputErrorString("ShellcodeExecCallback: unable to query memory region 0x%x", pBreakpointInfo->Address);
+ return FALSE;
+ }
+
+ DoOutputDebugString("ShellcodeExecCallback: Debug: About to scan region for a PE image (base 0x%x, size 0x%x).\n", meminfo.AllocationBase, meminfo.RegionSize);
+
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, meminfo.AllocationBase);
+
+ AllocationDumped = DumpPEsInRange(meminfo.AllocationBase, meminfo.RegionSize);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("ShellcodeExecCallback: PE image(s) detected and dumped.\n");
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ }
+ else
+ {
+ SetCapeMetaData(EXTRACTION_SHELLCODE, 0, NULL, meminfo.AllocationBase);
+
+ AllocationDumped = DumpMemory(meminfo.AllocationBase, meminfo.RegionSize);
+
+ if (AllocationDumped)
+ {
+ DoOutputDebugString("ShellcodeExecCallback: successfully dumped memory range at 0x%x.\n", AllocationBase);
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ }
+ }
+
+ if (!AllocationDumped)
+ {
+ DoOutputDebugString("ShellcodeExecCallback: failed to dump memory range at 0x%x.\n", AllocationBase);
+ ExtractionClearAll();
+ }
+
+ DoOutputDebugString("ShellcodeExecCallback executed successfully.\n");
+
+ return TRUE;
+}
+
+BOOL BaseAddressWriteCallback(PBREAKPOINTINFO pBreakpointInfo, struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ PIMAGE_DOS_HEADER pDosHeader;
+ unsigned int Register;
+
+ if (pBreakpointInfo == NULL)
+ {
+ DoOutputDebugString("BaseAddressWriteCallback executed with pBreakpointInfo NULL.\n");
+ return FALSE;
+ }
+
+ if (pBreakpointInfo->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("BaseAddressWriteCallback executed with NULL thread handle.\n");
+ return FALSE;
+ }
+
+ DoOutputDebugString("BaseAddressWriteCallback: Breakpoint %i at Address 0x%x.\n", pBreakpointInfo->Register, pBreakpointInfo->Address);
+
+ AllocationWriteDetected = TRUE;
+
+ if (*(WORD*)pBreakpointInfo->Address == IMAGE_DOS_SIGNATURE)
+ {
+ DoOutputDebugString("BaseAddressWriteCallback: MZ header found.\n");
+
+ pDosHeader = (PIMAGE_DOS_HEADER)pBreakpointInfo->Address;
+
+ if (pDosHeader->e_lfanew && (unsigned int)pDosHeader->e_lfanew < PE_HEADER_LIMIT)
+ {
+ if (*(DWORD*)((unsigned char*)pDosHeader + pDosHeader->e_lfanew) == IMAGE_NT_SIGNATURE)
+ {
+ PeImageDetected = TRUE;
+
+ SetCapeMetaData(EXTRACTION_PE, 0, NULL, AllocationBase);
+
+ if (DumpPEsInRange(AllocationBase, AllocationSize))
+ {
+ AllocationDumped = TRUE;
+ DoOutputDebugString("BaseAddressWriteCallback: successfully dumped module.\n");
+ ContextClearAllBreakpoints(ExceptionInfo->ContextRecord);
+ return TRUE;
+ }
+ else
+ {
+ DoOutputDebugString("BaseAddressWriteCallback: failed to dump PE module.\n");
+ }
+ }
+ else
+ {
+ // Deal with the situation where the breakpoint triggers after e_lfanew has already been written
+ if (ContextUpdateCurrentBreakpoint(ExceptionInfo->ContextRecord, sizeof(DWORD), (BYTE*)pDosHeader + pDosHeader->e_lfanew, BP_WRITE, PEHeaderWriteCallback))
+ {
+#ifdef _WIN64
+ DoOutputDebugString("BaseAddressWriteCallback: set write bp on e_lfanew write location 0x%x (RIP = 0x%x)\n", (BYTE*)pDosHeader + pDosHeader->e_lfanew, ExceptionInfo->ContextRecord->Rip);
+#else
+ DoOutputDebugString("BaseAddressWriteCallback: set write bp on e_lfanew write location 0x%x (EIP = 0x%x)\n", (BYTE*)pDosHeader + pDosHeader->e_lfanew, ExceptionInfo->ContextRecord->Eip);
+#endif
+ }
+ else
+ {
+ DoOutputDebugString("BaseAddressWriteCallback: ContextUpdateCurrentBreakpoint failed\n");
+ return FALSE;
+ }
+ }
+ }
+ //e_lfanew is a long, therefore dword in size
+ else if (ContextUpdateCurrentBreakpoint(ExceptionInfo->ContextRecord, sizeof(DWORD), (BYTE*)&pDosHeader->e_lfanew, BP_WRITE, PEPointerWriteCallback))
+ {
+#ifdef _WIN64
+ DoOutputDebugString("BaseAddressWriteCallback: set write bp on e_lfanew write location: 0x%x (RIP = 0x%x)\n", (BYTE*)&pDosHeader->e_lfanew, ExceptionInfo->ContextRecord->Rip);
+#else
+ DoOutputDebugString("BaseAddressWriteCallback: set write bp on e_lfanew write location: 0x%x (EIP = 0x%x)\n", (BYTE*)&pDosHeader->e_lfanew, ExceptionInfo->ContextRecord->Eip);
+#endif
+ }
+ else
+ {
+ DoOutputDebugString("BaseAddressWriteCallback: ContextUpdateCurrentBreakpoint failed\n");
+ return FALSE;
+ }
+ }
+ else if (*(BYTE*)pBreakpointInfo->Address == 'M')
+ {
+ // Cover the case where a PE file is being written a byte at a time
+ DoOutputDebugString("BaseAddressWriteCallback: M written to first byte, awaiting next byte.\n");
+
+ // We do nothing and hope that the 4D byte isn't code!
+ }
+ else
+ {
+ DoOutputDebugString("BaseAddressWriteCallback: byte written to 0x%x: 0x%x.\n", pBreakpointInfo->Address, *(BYTE*)pBreakpointInfo->Address);
+
+ if (AllocationBaseExecBpSet == TRUE)
+ {
+ DoOutputDebugString("BaseAddressWriteCallback: allocation exec bp already set, doing nothing.\n");
+ return TRUE;
+ }
+
+ // we add an exec breakpoint on address 0 in case it's shellcode, but leave the write bp in case it's an encrypted PE
+ if (ContextSetNextAvailableBreakpoint(ExceptionInfo->ContextRecord, &Register, 0, (BYTE*)AllocationBase, BP_EXEC, MidPageExecCallback))
+ {
+ AllocationBaseExecBpSet = TRUE;
+#ifdef _WIN64
+ DoOutputDebugString("BaseAddressWriteCallback: Execution breakpoint %d set base address: 0x%x, AllocationBaseExecBpSet = %d (RIP = 0x%x)\n", Register, AllocationBase, AllocationBaseExecBpSet, ExceptionInfo->ContextRecord->Rip);
+#else
+ DoOutputDebugString("BaseAddressWriteCallback: Execution breakpoint %d set base address: 0x%x, AllocationBaseExecBpSet = %d (EIP = 0x%x)\n", Register, AllocationBase, AllocationBaseExecBpSet, ExceptionInfo->ContextRecord->Eip);
+#endif
+ }
+ else
+ {
+ if (ContextUpdateCurrentBreakpoint(ExceptionInfo->ContextRecord, 0, (BYTE*)AllocationBase, BP_EXEC, MidPageExecCallback))
+ {
+ AllocationBaseExecBpSet = TRUE;
+ DoOutputDebugString("BaseAddressWriteCallback: Unable to add additional breakpoint, replacing existing write bp with execution bp.\n");
+ }
+ else
+ {
+ DoOutputDebugString("BaseAddressWriteCallback: Error: Failed to replace existing write bp with execution bp.\n");
+ return FALSE;
+ }
+ }
+ }
+
+ DoOutputDebugString("BaseAddressWriteCallback executed successfully.\n");
+
+ return TRUE;
+}
+
+BOOL SetMidPageBreakpoint(PVOID *Address, SIZE_T Size)
+{
+ DWORD ThreadId;
+ unsigned int Register;
+
+ ThreadId = GetCurrentThreadId();
+
+ AllocationSize = Size;
+ AllocationBase = Address;
+ CapeMetaData->Address = Address;
+
+ AllocationWriteDetected = FALSE;
+ PeImageDetected = FALSE;
+ AllocationDumped = FALSE;
+ AllocationBaseExecBpSet = FALSE;
+ EntryPointExecBpSet = FALSE;
+
+ DoOutputDebugString("SetMidPageBreakpoint: AllocationBase: 0x%x, AllocationSize: 0x%x, ThreadId: 0x%x\n", AllocationBase, AllocationSize, ThreadId);
+
+ if (AllocationSize == 0 || AllocationBase == NULL || ThreadId == 0)
+ {
+ DoOutputDebugString("SetMidPageBreakpoint: Error, one of the following is NULL: 0x%x, AllocationSize: 0x%x, ThreadId: 0x%x\n", AllocationBase, AllocationSize, ThreadId);
+ return FALSE;
+ }
+
+ if (!SetNextAvailableBreakpoint(ThreadId, &Register, 0, (BYTE*)Address, BP_EXEC, MidPageExecCallback))
+ {
+ DoOutputDebugString("SetMidPageBreakpoint: SetNextAvailableBreakpoint failed to set exec bp on executable address 0x%x.\n", Address);
+ return FALSE;
+ }
+ else
+ {
+ DoOutputDebugString("SetMidPageBreakpoint: Set exec breakpoint on protected address: 0x%x\n", Address);
+ }
+
+ return TRUE;
+}
+
+BOOL SetInitialWriteBreakpoint(PVOID *Address, SIZE_T RegionSize)
+{
+ DWORD ThreadId;
+ unsigned int Register;
+
+ ThreadId = GetCurrentThreadId();
+
+ AllocationSize = RegionSize;
+ AllocationBase = Address;
+ CapeMetaData->Address = Address;
+
+ AllocationWriteDetected = FALSE;
+ PeImageDetected = FALSE;
+ AllocationDumped = FALSE;
+ AllocationBaseWriteBpSet = FALSE;
+ AllocationBaseExecBpSet = FALSE;
+ EntryPointExecBpSet = FALSE;
+
+ DoOutputDebugString("SetInitialWriteBreakpoint: AllocationBase: 0x%x, AllocationSize: 0x%x, ThreadId: 0x%x\n", AllocationBase, AllocationSize, ThreadId);
+
+ if (AllocationSize == 0 || AllocationBase == NULL || ThreadId == 0)
+ {
+ DoOutputDebugString("SetInitialWriteBreakpoint: Error, one of the following is NULL: 0x%x, AllocationSize: 0x%x, ThreadId: 0x%x\n", AllocationBase, AllocationSize, ThreadId);
+ return FALSE;
+ }
+
+ if (SetNextAvailableBreakpoint(ThreadId, &Register, sizeof(WORD), (BYTE*)AllocationBase, BP_WRITE, BaseAddressWriteCallback))
+ {
+ DoOutputDebugString("SetInitialWriteBreakpoint: Breakpoint %d set write on word at base address: 0x%x\n", Register, AllocationBase);
+ AllocationBaseWriteBpSet = TRUE;
+ }
+ else
+ {
+ DoOutputDebugString("SetInitialWriteBreakpoint: SetNextAvailableBreakpoint failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
\ No newline at end of file
diff --git a/CAPE/Debugger.c b/CAPE/Debugger.c
index 874fcd5..a426c72 100644
--- a/CAPE/Debugger.c
+++ b/CAPE/Debugger.c
@@ -15,13 +15,13 @@ 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 .
*/
-#ifndef _WIN64
#include
#include
#include
#include
#include
#include "Debugger.h"
+#include "..\alloc.h"
#include "..\config.h"
#include "..\pipe.h"
@@ -49,7 +49,7 @@ typedef struct _DR7
DWORD PAD1 : 3;
DWORD GD : 1; //General Detect Enable
DWORD PAD2 : 1;
- DWORD Pad3 : 1;
+ DWORD PAD3 : 1;
DWORD RWE0 : 2; //Read/Write/Execute bp0
DWORD LEN0 : 2; //Length bp0
DWORD RWE1 : 2; //Read/Write/Execute bp1
@@ -65,17 +65,31 @@ typedef struct _DR7
#define DEBUG_REGISTER_DATA_SIZES {1, 2, 4}
#define DEBUG_REGISTER_LENGTH_MASKS {0xFFFFFFFF, 0, 1, 0xFFFFFFFF, 3}
+typedef struct _LSA_UNICODE_STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+ PWSTR Buffer;
+} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
+
+typedef struct _INJECT_STRUCT {
+ ULONG_PTR LdrLoadDllAddress;
+ UNICODE_STRING DllName;
+ HANDLE OutHandle;
+} INJECT_STRUCT, *PINJECT_STRUCT;
+
DWORD LengthMask[MAX_DEBUG_REGISTER_DATA_SIZE + 1] = DEBUG_REGISTER_LENGTH_MASKS;
DWORD MainThreadId;
struct ThreadBreakpoints *MainThreadBreakpointList;
-LPTOP_LEVEL_EXCEPTION_FILTER OriginalExceptionHandler;
-LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo);
SINGLE_STEP_HANDLER SingleStepHandler;
-DWORD WINAPI PipeThread(LPVOID lpParam);
-DWORD RemoteFuncAddress;
-HANDLE hParentPipe;
+GUARD_PAGE_HANDLER GuardPageHandler;
+HANDLE hCapePipe;
+
+extern ULONG_PTR g_our_dll_base;
+extern DWORD g_our_dll_size;
+extern LONG WINAPI cuckoomon_exception_handler(__in struct _EXCEPTION_POINTERS *ExceptionInfo);
+extern BOOL ExtractionGuardPageHandler(struct _EXCEPTION_POINTERS* ExceptionInfo);
extern unsigned int address_is_in_stack(DWORD Address);
extern BOOL WoW64fix(void);
extern BOOL WoW64PatchBreakpoint(unsigned int Register);
@@ -85,14 +99,307 @@ extern DWORD MyGetThreadId(HANDLE hThread);
extern void DoOutputDebugString(_In_ LPCTSTR lpOutputString, ...);
extern void DoOutputErrorString(_In_ LPCTSTR lpOutputString, ...);
-LPTOP_LEVEL_EXCEPTION_FILTER OriginalExceptionHandler;
-
-PVOID OEP;
-
void DebugOutputThreadBreakpoints();
-BOOL RestoreExecutionBreakpoint(PCONTEXT Context);
+BOOL ResumeAfterExecutionBreakpoint(PCONTEXT Context);
BOOL SetSingleStepMode(PCONTEXT Context, PVOID Handler);
BOOL ClearSingleStepMode(PCONTEXT Context);
+unsigned int TrapIndex;
+
+//**************************************************************************************
+BOOL IsInGuardPages(PVOID Address)
+//**************************************************************************************
+{
+ PGUARDPAGES CurrentGuardPages = GuardPageList;
+
+ if (GuardPageList == NULL)
+ return FALSE;
+
+ while (CurrentGuardPages)
+ {
+ if ((DWORD_PTR)Address >= (DWORD_PTR)CurrentGuardPages->BaseAddress && (DWORD_PTR)Address < ((DWORD_PTR)CurrentGuardPages->BaseAddress + (DWORD_PTR)CurrentGuardPages->RegionSize))
+ return TRUE;
+
+ CurrentGuardPages = CurrentGuardPages->NextGuardPages;
+ }
+
+ return FALSE;
+}
+
+//**************************************************************************************
+PGUARDPAGES GetGuardPages(PVOID Address)
+//**************************************************************************************
+{
+ PGUARDPAGES CurrentGuardPages = GuardPageList;
+
+ if (Address == NULL)
+ {
+ DoOutputDebugString("GetGuardPages: NULL passed as argument - error.\n");
+ return FALSE;
+ }
+
+ if (GuardPageList == NULL)
+ {
+ DoOutputDebugString("GetGuardPages: failed to obtain initial guard page list.\n");
+ return FALSE;
+ }
+
+ while (CurrentGuardPages)
+ {
+ if ((DWORD_PTR)Address >= (DWORD_PTR)CurrentGuardPages->BaseAddress && (DWORD_PTR)Address < ((DWORD_PTR)CurrentGuardPages->BaseAddress + (DWORD_PTR)CurrentGuardPages->RegionSize))
+ return CurrentGuardPages;
+
+ CurrentGuardPages = CurrentGuardPages->NextGuardPages;
+ }
+
+ DoOutputDebugString("GetGuardPages: failed to find guard pages in list.\n");
+
+ return NULL;
+}
+
+//**************************************************************************************
+BOOL DropGuardPages(PGUARDPAGES GuardPages)
+//**************************************************************************************
+{
+ // DEBUG
+ DoOutputDebugString("DropGuardPages entry.\n");
+
+ PGUARDPAGES CurrentGuardPages, PreviousGuardPages;
+
+ if (GuardPages == NULL)
+ {
+ DoOutputDebugString("DropGuardPages: NULL passed as argument - error.\n");
+ return FALSE;
+ }
+
+ PreviousGuardPages = NULL;
+
+ if (GuardPageList == NULL)
+ {
+ DoOutputDebugString("DropGuardPages: failed to obtain initial guard page list.\n");
+ return FALSE;
+ }
+
+ CurrentGuardPages = GuardPageList;
+
+ while (CurrentGuardPages)
+ {
+ DoOutputDebugString("DropGuardPages: CurrentGuardPages 0x%x.\n", CurrentGuardPages);
+
+ if (CurrentGuardPages == GuardPages)
+ {
+ DoOutputDebugString("DropGuardPages: About to unlink.\n");
+ // Unlink this from the list and free the memory
+ if (PreviousGuardPages && CurrentGuardPages->NextGuardPages)
+ {
+ DoOutputDebugString("DropGuardPages: removed pages 0x%x-0x%x from guard page list.\n", GuardPages->BaseAddress, (DWORD_PTR)GuardPages->BaseAddress + GuardPages->RegionSize);
+ PreviousGuardPages->NextGuardPages = CurrentGuardPages->NextGuardPages;
+ }
+ else if (PreviousGuardPages && CurrentGuardPages->NextGuardPages == NULL)
+ {
+ DoOutputDebugString("DropGuardPages: removed pages 0x%x-0x%x from the end of the guard page list.\n", GuardPages->BaseAddress, (DWORD_PTR)GuardPages->BaseAddress + GuardPages->RegionSize);
+ PreviousGuardPages->NextGuardPages = NULL;
+ }
+ else if (!PreviousGuardPages)
+ {
+ DoOutputDebugString("DropGuardPages: removed pages 0x%x-0x%x from the head of the guard page list.\n", GuardPages->BaseAddress, (DWORD_PTR)GuardPages->BaseAddress + GuardPages->RegionSize);
+ GuardPageList = NULL;
+ }
+
+ DoOutputDebugString("DropGuardPages: about to free the memory!\n");
+ free(CurrentGuardPages);
+
+ return TRUE;
+ }
+
+ PreviousGuardPages = CurrentGuardPages;
+ CurrentGuardPages = CurrentGuardPages->NextGuardPages;
+ }
+
+ DoOutputDebugString("DropGuardPages: failed to find guard pages in list.\n");
+
+ return FALSE;
+}
+
+//**************************************************************************************
+BOOL ReinstateGuardPages(PGUARDPAGES GuardPages)
+//**************************************************************************************
+{
+ DWORD OldProtect;
+ BOOL GuardPagesFound = FALSE;
+ PGUARDPAGES CurrentGuardPages = GuardPageList;
+ MEMORY_BASIC_INFORMATION MemInfo;
+ SIZE_T MatchingRegionSize;
+
+ if (GuardPageList == NULL)
+ return FALSE;
+
+ while (CurrentGuardPages)
+ {
+ if (GuardPages->BaseAddress == CurrentGuardPages->BaseAddress)
+ GuardPagesFound = TRUE;
+
+ CurrentGuardPages = CurrentGuardPages->NextGuardPages;
+ }
+
+ if (GuardPagesFound == FALSE)
+ {
+ DoOutputDebugString("ReinstateGuardPages: failed to locate guard page(s) in guard page list.\n");
+ return FALSE;
+ }
+
+ MatchingRegionSize = VirtualQuery(GuardPages->BaseAddress, &MemInfo, GuardPages->RegionSize);
+
+ if (!MatchingRegionSize)
+ {
+ DoOutputErrorString("ReinstateGuardPages: failed to query guard page(s) status in region 0x%x-0x%x", GuardPages->BaseAddress, (DWORD_PTR)GuardPages->BaseAddress + GuardPages->RegionSize);
+ return FALSE;
+ }
+
+ if (MatchingRegionSize == GuardPages->RegionSize && MemInfo.Protect & PAGE_GUARD)
+ {
+ DoOutputDebugString("ReinstateGuardPages: guard page(s) already set in region 0x%x-0x%x", GuardPages->BaseAddress, (DWORD_PTR)GuardPages->BaseAddress + GuardPages->RegionSize);
+ return FALSE;
+ }
+
+ if (!VirtualProtect(GuardPages->BaseAddress, GuardPages->RegionSize, GuardPages->Protect | PAGE_GUARD, &OldProtect))
+ {
+ DoOutputErrorString("ReinstateGuardPages: failed to reinstate guard page(s) on region 0x%x size 0x%x", GuardPages->BaseAddress, GuardPages->RegionSize);
+ return FALSE;
+ }
+
+ // This is unreliable if some pages no longer have PAGE_GUARD,
+ // i.e. they have been touched, while others haven't
+ //if (OldProtect != GuardPages->Protect)
+ //{
+ // DoOutputDebugString("ReinstateGuardPages error: inconsistency in protecton flags for region 0x%x-0x%x - OldProtect = 0x%x, GuardPages->Protect = 0x%x\n", GuardPages->BaseAddress, (DWORD_PTR)GuardPages->BaseAddress + GuardPages->RegionSize, OldProtect, GuardPages->Protect);
+ //}
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL DisableGuardPages(PGUARDPAGES GuardPages)
+//**************************************************************************************
+{
+ DWORD OldProtect;
+ BOOL GuardPagesFound = FALSE;
+ PGUARDPAGES CurrentGuardPages = GuardPageList;
+ MEMORY_BASIC_INFORMATION MemInfo;
+ SIZE_T MatchingRegionSize;
+
+ if (GuardPageList == NULL)
+ return FALSE;
+
+ while (CurrentGuardPages)
+ {
+ if (GuardPages->BaseAddress == CurrentGuardPages->BaseAddress)
+ GuardPagesFound = TRUE;
+
+ CurrentGuardPages = CurrentGuardPages->NextGuardPages;
+ }
+
+ if (GuardPagesFound == FALSE)
+ {
+ DoOutputDebugString("DisableGuardPages: failed to locate guard page(s) in guard page list.\n");
+ return FALSE;
+ }
+
+ MatchingRegionSize = VirtualQuery(GuardPages->BaseAddress, &MemInfo, GuardPages->RegionSize);
+
+ if (!MatchingRegionSize)
+ {
+ DoOutputErrorString("DisableGuardPages: failed to query guard page(s) status in region 0x%x-0x%x", GuardPages->BaseAddress, (DWORD_PTR)GuardPages->BaseAddress + GuardPages->RegionSize);
+ return FALSE;
+ }
+
+ if (MatchingRegionSize == GuardPages->RegionSize && !(MemInfo.Protect & PAGE_GUARD))
+ {
+ DoOutputDebugString("DisableGuardPages: guard page(s) not set in region 0x%x-0x%x", GuardPages->BaseAddress, (DWORD_PTR)GuardPages->BaseAddress + GuardPages->RegionSize);
+ return FALSE;
+ }
+
+ if (!VirtualProtect(GuardPages->BaseAddress, GuardPages->RegionSize, GuardPages->Protect, &OldProtect))
+ {
+ DoOutputErrorString("DisableGuardPages: failed to disable guard page(s) on region 0x%x-0x%x", GuardPages->BaseAddress, (DWORD_PTR)GuardPages->BaseAddress + GuardPages->RegionSize);
+ return FALSE;
+ }
+
+ //if (OldProtect != (GuardPages->Protect & PAGE_GUARD))
+ //{
+ // DoOutputDebugString("DisableGuardPages error: inconsistency in protecton flags for region 0x%x-0x%x - OldProtect = 0x%x, GuardPages->Protect = 0x%x\n", GuardPages->BaseAddress, (DWORD_PTR)GuardPages->BaseAddress + GuardPages->RegionSize, OldProtect, GuardPages->Protect);
+ //}
+
+ return TRUE;
+}
+
+//**************************************************************************************
+PGUARDPAGES CreateGuardPages()
+//**************************************************************************************
+{
+ if (GuardPageList == NULL)
+ {
+ GuardPageList = ((struct GuardPages*)malloc(sizeof(struct GuardPages)));
+
+ if (GuardPageList == NULL)
+ {
+ DoOutputDebugString("CreateGuardPages: failed to allocate memory for initial thread breakpoint list.\n");
+ return NULL;
+ }
+ memset(GuardPageList, 0, sizeof(struct GuardPages));
+ }
+
+ return GuardPageList;
+}
+
+//**************************************************************************************
+BOOL AddGuardPages(PVOID Address, SIZE_T RegionSize, ULONG Protect)
+//**************************************************************************************
+{
+ BOOL PageAlreadyGuarded;
+ PGUARDPAGES CurrentGuardPages, PreviousGuardPages;
+
+ PreviousGuardPages = NULL;
+
+ if (GuardPageList == NULL)
+ CreateGuardPages();
+
+ CurrentGuardPages = GuardPageList;
+
+ while (CurrentGuardPages)
+ {
+ if ((DWORD_PTR)Address >= (DWORD_PTR)CurrentGuardPages->BaseAddress && (DWORD_PTR)Address < ((DWORD_PTR)CurrentGuardPages->BaseAddress + (DWORD_PTR)CurrentGuardPages->RegionSize))
+ PageAlreadyGuarded = TRUE;
+ else
+ PageAlreadyGuarded = FALSE;
+
+ PreviousGuardPages = CurrentGuardPages;
+ CurrentGuardPages = CurrentGuardPages->NextGuardPages;
+ }
+
+ if (PageAlreadyGuarded == FALSE)
+ {
+ // We haven't found it in the linked list, so create a new one
+ CurrentGuardPages = PreviousGuardPages;
+
+ CurrentGuardPages->NextGuardPages = ((struct GuardPages*)malloc(sizeof(struct GuardPages)));
+
+ if (CurrentGuardPages->NextGuardPages == NULL)
+ {
+ DoOutputDebugString("AddGuardPages: Failed to allocate new guard page struct.\n");
+ return FALSE;
+ }
+ memset(CurrentGuardPages->NextGuardPages, 0, sizeof(struct GuardPages));
+
+ CurrentGuardPages->BaseAddress = Address;
+ CurrentGuardPages->RegionSize = RegionSize;
+ CurrentGuardPages->Protect = Protect;
+ CurrentGuardPages->WriteDetected = FALSE;
+ CurrentGuardPages->LastWriteAddress = NULL;
+ CurrentGuardPages->PagesDumped = FALSE;
+ }
+
+ return TRUE;
+}
//**************************************************************************************
PTHREADBREAKPOINTS GetThreadBreakpoints(DWORD ThreadId)
@@ -196,6 +503,8 @@ PTHREADBREAKPOINTS CreateThreadBreakpoints(DWORD ThreadId)
}
}
+ CurrentThreadBreakpoint->ThreadId = ThreadId;
+
for (Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
{
CurrentThreadBreakpoint->BreakpointInfo[Register].Register = Register;
@@ -205,23 +514,93 @@ PTHREADBREAKPOINTS CreateThreadBreakpoints(DWORD ThreadId)
return CurrentThreadBreakpoint;
}
+//**************************************************************************************
+BOOL GetNextAvailableBreakpoint(DWORD ThreadId, unsigned int* Register)
+//**************************************************************************************
+{
+ DWORD CurrentThreadId;
+ unsigned int i;
+
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint = MainThreadBreakpointList;
+
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ 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++)
+ {
+ if (CurrentThreadBreakpoint->BreakpointInfo[i].Address == NULL)
+ {
+ *Register = i;
+ return TRUE;
+ }
+ }
+ }
+
+ CurrentThreadBreakpoint = CurrentThreadBreakpoint->NextThreadBreakpoints;
+ }
+
+ return FALSE;
+}
+
+//**************************************************************************************
+BOOL ContextGetNextAvailableBreakpoint(PCONTEXT Context, unsigned int* Register)
+//**************************************************************************************
+{
+ unsigned int i;
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint;
+
+ CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
+
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("ContextGetNextAvailableBreakpoint: Creating new thread breakpoints for thread 0x%x.\n", GetCurrentThreadId());
+ CurrentThreadBreakpoint = CreateThreadBreakpoints(GetCurrentThreadId());
+ }
+
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("ContextGetNextAvailableBreakpoint: Cannot create new thread breakpoints - FATAL.\n");
+ return FALSE;
+ }
+
+ for (i=0; i < NUMBER_OF_DEBUG_REGISTERS; i++)
+ {
+ if (CurrentThreadBreakpoint->BreakpointInfo[i].Address == NULL)
+ {
+ *Register = i;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
//**************************************************************************************
void DebugOutputThreadBreakpoints()
//**************************************************************************************
{
unsigned int Register;
- PTHREADBREAKPOINTS CurrentThreadBreakpoints;
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint;
PBREAKPOINTINFO pBreakpointInfo;
- CurrentThreadBreakpoints = GetThreadBreakpoints(GetCurrentThreadId());
+ CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
for (Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
{
- pBreakpointInfo = &(CurrentThreadBreakpoints->BreakpointInfo[Register]);
+ pBreakpointInfo = &(CurrentThreadBreakpoint->BreakpointInfo[Register]);
if (pBreakpointInfo == NULL)
{
- DoOutputDebugString("CAPEExceptionFilter: Can't get BreakpointInfo - FATAL.\n");
+ 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",
@@ -234,6 +613,16 @@ void DebugOutputThreadBreakpoints()
}
}
+//**************************************************************************************
+void ShowStack(DWORD_PTR StackPointer, unsigned int NumberOfRecords)
+//**************************************************************************************
+{
+ unsigned int i;
+
+ for (i=0; iExceptionRecord->ExceptionAddress);
-
- CurrentThreadBreakpoints = GetThreadBreakpoints(GetCurrentThreadId());
-
- if (CurrentThreadBreakpoints == NULL)
- {
- DoOutputDebugString("CAPEExceptionFilter: Can't get thread breakpoints - FATAL.\n");
- return EXCEPTION_CONTINUE_SEARCH;
- }
-
// Test Dr6 to see if this is a breakpoint
BreakpointFlag = FALSE;
for (bp = 0; bp < NUMBER_OF_DEBUG_REGISTERS; bp++)
{
- if (ExceptionInfo->ContextRecord->Dr6 & (1 << bp))
+ if (ExceptionInfo->ContextRecord->Dr6 & (DWORD_PTR)(1 << bp))
{
BreakpointFlag = TRUE;
}
@@ -271,16 +650,38 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
// If not it's a single-step
if (BreakpointFlag == FALSE)
{
- //if (SingleStepHandler(ExceptionInfo))
- SingleStepHandler(ExceptionInfo);
+ if (SingleStepHandler)
+ SingleStepHandler(ExceptionInfo);
+ else if (TrapIndex)
+ // this is from StepOverExecutionBreakpoint
+ {
+ DoOutputDebugString("CAPEExceptionFilter: Stepping over execution breakpoint to: 0x%x\n", ExceptionInfo->ExceptionRecord->ExceptionAddress);
+ ResumeAfterExecutionBreakpoint(ExceptionInfo->ContextRecord);
+ }
+ else
+ {
+ DoOutputDebugString("CAPEExceptionFilter: Error, unhandled single-step exception at: 0x%x\n", ExceptionInfo->ExceptionRecord->ExceptionAddress);
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
return EXCEPTION_CONTINUE_EXECUTION;
}
+ DoOutputDebugString("Entering CAPEExceptionFilter: breakpoint hit: 0x%x\n", ExceptionInfo->ExceptionRecord->ExceptionAddress);
+
+ CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
+
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("CAPEExceptionFilter: Can't get thread breakpoints - FATAL.\n");
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
for (bp = 0; bp < NUMBER_OF_DEBUG_REGISTERS; bp++)
{
- if (ExceptionInfo->ContextRecord->Dr6 & (1 << bp))
+ if (ExceptionInfo->ContextRecord->Dr6 & (DWORD_PTR)(1 << bp))
{
- pBreakpointInfo = &(CurrentThreadBreakpoints->BreakpointInfo[bp]);
+ pBreakpointInfo = &(CurrentThreadBreakpoint->BreakpointInfo[bp]);
if (pBreakpointInfo == NULL)
{
@@ -290,25 +691,25 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
if (pBreakpointInfo->Register == bp)
{
- if (bp == 0 && ((DWORD)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr0))
+ 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)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr1))
+ 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)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr2))
+ 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)pBreakpointInfo->Address != ExceptionInfo->ContextRecord->Dr3))
+ 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);
-
- if (bp == 0 && ((DWORD)pBreakpointInfo->Type != ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE0))
+#ifndef _WIN64
+ if (bp == 0 && ((DWORD_PTR)pBreakpointInfo->Type != ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE0))
{
- if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE0 == BP_WRITE && address_is_in_stack((DWORD)pBreakpointInfo->Address))
+ 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);
- SetExceptionHardwareBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->Callback);
+ ContextSetBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->Callback);
}
else
{
@@ -318,11 +719,11 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
}
if (bp == 1 && ((DWORD)pBreakpointInfo->Type != ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE1))
{
- if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE1 == BP_WRITE && address_is_in_stack((DWORD)pBreakpointInfo->Address))
+ 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);
- SetExceptionHardwareBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->Callback);
+ ContextSetBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->Callback);
}
else
{
@@ -332,11 +733,11 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
}
if (bp == 2 && ((DWORD)pBreakpointInfo->Type != ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE2))
{
- if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE2 == BP_WRITE && address_is_in_stack((DWORD)pBreakpointInfo->Address))
+ 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);
- SetExceptionHardwareBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->Callback);
+ ContextSetBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->Callback);
}
else
{
@@ -346,11 +747,11 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
}
if (bp == 3 && ((DWORD)pBreakpointInfo->Type != ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE3))
{
- if (pBreakpointInfo->Type == BP_READWRITE && ((PDR7)&(ExceptionInfo->ContextRecord->Dr7))->RWE3 == BP_WRITE && address_is_in_stack((DWORD)pBreakpointInfo->Address))
+ 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);
- SetExceptionHardwareBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->Callback);
+ ContextSetBreakpoint(ExceptionInfo->ContextRecord, pBreakpointInfo->Register, pBreakpointInfo->Size, (BYTE*)pBreakpointInfo->Address, pBreakpointInfo->Type, pBreakpointInfo->Callback);
}
else
{
@@ -358,6 +759,7 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
CheckDebugRegisters(0, ExceptionInfo->ContextRecord);
}
}
+#endif // !_WIN64
}
}
}
@@ -375,13 +777,78 @@ LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
return EXCEPTION_CONTINUE_EXECUTION;
}
-
- // Some other exception occurred. Pass it to next handler
+ // 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;
+ }
+
+ //DoOutputDebugString("Entering CAPEExceptionFilter: guarded page access at 0x%x by 0x%x\n", ExceptionInfo->ExceptionRecord->ExceptionInformation[1], ExceptionInfo->ExceptionRecord->ExceptionAddress);
+
+ if (IsInGuardPages((PVOID)ExceptionInfo->ExceptionRecord->ExceptionInformation[1]))
+ {
+ if (GuardPageHandler)
+ {
+ if (GuardPageHandler(ExceptionInfo))
+ return EXCEPTION_CONTINUE_EXECUTION;
+ else
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else
+ {
+ DoOutputDebugString("CAPEExceptionFilter: Error, no page guard handler for CAPE guard page exception.\n");
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
+ else
+ {
+ DoOutputDebugString("CAPEExceptionFilter: exception at 0x%x not within CAPE guarded page.\n", ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
+ 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)
+ {
+ 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;
+ }
+ 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);
+ }
+
+ 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 in cuckoomon caught (expected in memory scans), passing to next handler.\n");
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ // Some other exception occurred. Pass it to next handler.
return EXCEPTION_CONTINUE_SEARCH;
}
//**************************************************************************************
-BOOL SetExceptionDebugRegister
+BOOL ContextSetDebugRegister
//**************************************************************************************
(
PCONTEXT Context,
@@ -393,37 +860,37 @@ BOOL SetExceptionDebugRegister
{
DWORD Length;
- PDWORD Dr0 = &(Context->Dr0);
- PDWORD Dr1 = &(Context->Dr1);
- PDWORD Dr2 = &(Context->Dr2);
- PDWORD Dr3 = &(Context->Dr3);
+ PDWORD_PTR Dr0 = &(Context->Dr0);
+ PDWORD_PTR Dr1 = &(Context->Dr1);
+ PDWORD_PTR Dr2 = &(Context->Dr2);
+ PDWORD_PTR Dr3 = &(Context->Dr3);
PDR7 Dr7 = (PDR7)&(Context->Dr7);
if ((unsigned int)Type > 3)
{
- DoOutputDebugString("SetExceptionDebugRegister: %d is an invalid breakpoint type, must be 0-3.\n", Type);
+ DoOutputDebugString("ContextSetDebugRegister: %d is an invalid breakpoint type, must be 0-3.\n", Type);
return FALSE;
}
if (Type == 2)
{
- DoOutputDebugString("SetExceptionDebugRegister: The value 2 is a 'reserved' breakpoint type, ultimately invalid.\n");
+ DoOutputDebugString("ContextSetDebugRegister: The value 2 is a 'reserved' breakpoint type, ultimately invalid.\n");
return FALSE;
}
if (Register < 0 || Register > 3)
{
- DoOutputDebugString("SetExceptionDebugRegister: %d is an invalid register, must be 0-3.\n", Register);
+ DoOutputDebugString("ContextSetDebugRegister: %d is an invalid register, must be 0-3.\n", Register);
return FALSE;
}
if (Size < 0 || Size > 8)
{
- DoOutputDebugString("SetExceptionDebugRegister: %d is an invalid Size, must be 1, 2, 4 or 8.\n", Size);
+ DoOutputDebugString("ContextSetDebugRegister: %d is an invalid Size, must be 1, 2, 4 or 8.\n", Size);
return FALSE;
}
- DoOutputDebugString("Setting breakpoint %i within Context, Size=0x%x, Address=0x%x and Type=0x%x.\n", Register, Size, Address, Type);
+ DoOutputDebugString("ContextSetDebugRegister: Setting breakpoint %i within Context, Size=0x%x, Address=0x%x and Type=0x%x.\n", Register, Size, Address, Type);
Length = LengthMask[Size];
@@ -431,33 +898,35 @@ BOOL SetExceptionDebugRegister
if (Type == BP_EXEC)
Length = 0;
- if (Type == BP_READWRITE && address_is_in_stack((DWORD)Address))
+#ifndef _WIN64
+ if (Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)Address))
WoW64PatchBreakpoint(Register);
+#endif
if (Register == 0)
{
- *Dr0 = (DWORD)Address;
+ *Dr0 = (DWORD_PTR)Address;
Dr7->LEN0 = Length;
Dr7->RWE0 = Type;
Dr7->L0 = 1;
}
else if (Register == 1)
{
- *Dr1 = (DWORD)Address;
+ *Dr1 = (DWORD_PTR)Address;
Dr7->LEN1 = Length;
Dr7->RWE1 = Type;
Dr7->L1 = 1;
}
else if (Register == 2)
{
- *Dr2 = (DWORD)Address;
+ *Dr2 = (DWORD_PTR)Address;
Dr7->LEN2 = Length;
Dr7->RWE2 = Type;
Dr7->L2 = 1;
}
else if (Register == 3)
{
- *Dr3 = (DWORD)Address;
+ *Dr3 = (DWORD_PTR)Address;
Dr7->LEN3 = Length;
Dr7->RWE3 = Type;
Dr7->L3 = 1;
@@ -483,10 +952,10 @@ BOOL SetDebugRegister
DWORD Length;
CONTEXT Context;
- PDWORD Dr0 = &Context.Dr0;
- PDWORD Dr1 = &Context.Dr1;
- PDWORD Dr2 = &Context.Dr2;
- PDWORD Dr3 = &Context.Dr3;
+ PDWORD_PTR Dr0 = &Context.Dr0;
+ PDWORD_PTR Dr1 = &Context.Dr1;
+ PDWORD_PTR Dr2 = &Context.Dr2;
+ PDWORD_PTR Dr3 = &Context.Dr3;
PDR7 Dr7 = (PDR7)&(Context.Dr7);
if ((unsigned int)Type > 3)
@@ -513,12 +982,13 @@ BOOL SetDebugRegister
return FALSE;
}
- DoOutputDebugString("Setting breakpoint %i hThread=0x%x, Size=0x%x, Address=0x%x and Type=0x%x.\n", Register, hThread, Size, Address, Type);
+ DoOutputDebugString("SetDebugRegister: Setting breakpoint %i hThread=0x%x, Size=0x%x, Address=0x%x and Type=0x%x.\n", Register, hThread, Size, Address, Type);
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
if (!GetThreadContext(hThread, &Context))
{
+ DoOutputErrorString("SetDebugRegister: GetThreadContext failed");
return FALSE;
}
@@ -528,33 +998,35 @@ BOOL SetDebugRegister
if (Type == BP_EXEC)
Length = 0;
- if (Type == BP_READWRITE && address_is_in_stack((DWORD)Address))
+#ifndef _WIN64
+ if (Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)Address))
WoW64PatchBreakpoint(Register);
+#endif
if (Register == 0)
{
- *Dr0 = (DWORD)Address;
+ *Dr0 = (DWORD_PTR)Address;
Dr7->LEN0 = Length;
Dr7->RWE0 = Type;
Dr7->L0 = 1;
}
else if (Register == 1)
{
- *Dr1 = (DWORD)Address;
+ *Dr1 = (DWORD_PTR)Address;
Dr7->LEN1 = Length;
Dr7->RWE1 = Type;
Dr7->L1 = 1;
}
else if (Register == 2)
{
- *Dr2 = (DWORD)Address;
+ *Dr2 = (DWORD_PTR)Address;
Dr7->LEN2 = Length;
Dr7->RWE2 = Type;
Dr7->L2 = 1;
}
else if (Register == 3)
{
- *Dr3 = (DWORD)Address;
+ *Dr3 = (DWORD_PTR)Address;
Dr7->LEN3 = Length;
Dr7->RWE3 = Type;
Dr7->L3 = 1;
@@ -566,31 +1038,35 @@ BOOL SetDebugRegister
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
if (!SetThreadContext(hThread, &Context))
- return FALSE;
-
+ {
+ DoOutputErrorString("SetDebugRegister: SetThreadContext failed");
+ return FALSE;
+ }
+
return TRUE;
}
//**************************************************************************************
-BOOL ClearAllDebugRegisters(HANDLE hThread)
+BOOL ContextCheckDebugRegisters(PCONTEXT Context)
//**************************************************************************************
-{
- CONTEXT Context;
- Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
-
- if (!GetThreadContext(hThread, &Context))
- return FALSE;
+{
+ 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);
+ DoOutputDebugString("Dr2 0x%x, Dr7->LEN2 %i, Dr7->RWE2 %i, Dr7->L2 %i\n", Context->Dr2, Dr7->LEN2, Dr7->RWE2, Dr7->L2);
+ DoOutputDebugString("Dr3 0x%x, Dr7->LEN3 %i, Dr7->RWE3 %i, Dr7->L3 %i\n", Context->Dr3, Dr7->LEN3, Dr7->RWE3, Dr7->L3);
+ DoOutputDebugString("Dr6 0x%x\n", Context->Dr6);
- Context.Dr0 = 0;
- Context.Dr1 = 0;
- Context.Dr2 = 0;
- Context.Dr3 = 0;
- Context.Dr6 = 0;
- Context.Dr7 = 0;
-
- if (!SetThreadContext(hThread, &Context))
- return FALSE;
-
return TRUE;
}
@@ -599,15 +1075,15 @@ BOOL CheckDebugRegisters(HANDLE hThread, PCONTEXT pContext)
//**************************************************************************************
{
CONTEXT Context;
- PDWORD Dr0 = &Context.Dr0;
- PDWORD Dr1 = &Context.Dr1;
- PDWORD Dr2 = &Context.Dr2;
- PDWORD Dr3 = &Context.Dr3;
+ PDWORD_PTR Dr0 = &Context.Dr0;
+ PDWORD_PTR Dr1 = &Context.Dr1;
+ PDWORD_PTR Dr2 = &Context.Dr2;
+ PDWORD_PTR Dr3 = &Context.Dr3;
PDR7 Dr7 = (PDR7)&(Context.Dr7);
if (!hThread && !pContext)
{
- DoOutputDebugString("CheckDebugRegisters - no arguments supplied.\n");
+ DoOutputDebugString("CheckDebugRegisters - reqruied arguments missing.\n");
return FALSE;
}
@@ -636,10 +1112,100 @@ BOOL CheckDebugRegisters(HANDLE hThread, PCONTEXT pContext)
}
//**************************************************************************************
-BOOL ClearExceptionHardwareBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpointInfo)
+BOOL ContextClearAllBreakpoints(PCONTEXT Context)
+//**************************************************************************************
+{
+ unsigned int i;
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint;
+
+ CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
+
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("ContextClearAllBreakpoints: No breakpoints found for current thread 0x%x.\n", GetCurrentThreadId());
+ return FALSE;
+ }
+
+ for (i=0; i < NUMBER_OF_DEBUG_REGISTERS; i++)
+ {
+ CurrentThreadBreakpoint->BreakpointInfo[i].Register = 0;
+ CurrentThreadBreakpoint->BreakpointInfo[i].Size = 0;
+ CurrentThreadBreakpoint->BreakpointInfo[i].Address = NULL;
+ CurrentThreadBreakpoint->BreakpointInfo[i].Type = 0;
+ CurrentThreadBreakpoint->BreakpointInfo[i].Callback = NULL;
+ }
+
+ Context->Dr0 = 0;
+ Context->Dr1 = 0;
+ Context->Dr2 = 0;
+ Context->Dr3 = 0;
+ Context->Dr6 = 0;
+ Context->Dr7 = 0;
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL ClearAllBreakpoints(DWORD ThreadId)
//**************************************************************************************
{
- PDWORD Dr0, Dr1, Dr2, Dr3;
+ CONTEXT Context;
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint;
+ unsigned int Register;
+ DWORD CurrentThreadId;
+
+ CurrentThreadBreakpoint = MainThreadBreakpointList;
+
+ while (CurrentThreadBreakpoint)
+ {
+ CurrentThreadId = MyGetThreadId(CurrentThreadBreakpoint->ThreadHandle);
+
+ if (CurrentThreadId == ThreadId)
+ {
+ for (Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
+ {
+ CurrentThreadBreakpoint->BreakpointInfo[Register].Register = 0;
+ CurrentThreadBreakpoint->BreakpointInfo[Register].Size = 0;
+ CurrentThreadBreakpoint->BreakpointInfo[Register].Address = NULL;
+ CurrentThreadBreakpoint->BreakpointInfo[Register].Type = 0;
+ CurrentThreadBreakpoint->BreakpointInfo[Register].Callback = NULL;
+ }
+
+ Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+
+ if (!GetThreadContext(CurrentThreadBreakpoint->ThreadHandle, &Context))
+ {
+ DoOutputDebugString("ClearAllBreakpoints: Error getting thread context (thread %d).\n", CurrentThreadId);
+ return FALSE;
+ }
+
+ Context.Dr0 = 0;
+ Context.Dr1 = 0;
+ Context.Dr2 = 0;
+ Context.Dr3 = 0;
+ Context.Dr6 = 0;
+ Context.Dr7 = 0;
+
+ if (!SetThreadContext(CurrentThreadBreakpoint->ThreadHandle, &Context))
+ {
+ DoOutputDebugString("ClearAllBreakpoints: Error setting thread context (thread %d).\n", CurrentThreadId);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+ else
+ CurrentThreadBreakpoint = CurrentThreadBreakpoint->NextThreadBreakpoints;
+ }
+
+ return FALSE;
+}
+
+//**************************************************************************************
+BOOL ContextClearBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpointInfo)
+//**************************************************************************************
+{
+ PDWORD_PTR Dr0, Dr1, Dr2, Dr3;
PDR7 Dr7;
if (Context == NULL)
@@ -651,7 +1217,7 @@ BOOL ClearExceptionHardwareBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpo
Dr3 = &(Context->Dr3);
Dr7 = (PDR7)&(Context->Dr7);
- DoOutputDebugString("Clearing Context breakpoint %i\n", pBreakpointInfo->Register);
+ DoOutputDebugString("ContextClearBreakpoint: Clearing Context breakpoint %i\n", pBreakpointInfo->Register);
if (pBreakpointInfo->Register == 0)
{
@@ -682,8 +1248,10 @@ BOOL ClearExceptionHardwareBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpo
Dr7->L3 = 0;
}
- if (pBreakpointInfo->Type == BP_READWRITE && address_is_in_stack((DWORD)pBreakpointInfo->Address))
+#ifndef _WIN64
+ if (pBreakpointInfo->Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)pBreakpointInfo->Address))
WoW64UnpatchBreakpoint(pBreakpointInfo->Register);
+#endif
Context->Dr6 = 0;
@@ -695,6 +1263,54 @@ BOOL ClearExceptionHardwareBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpo
return TRUE;
}
+//**************************************************************************************
+BOOL ClearBreakpointsInRange(DWORD ThreadId, PVOID BaseAddress, SIZE_T Size)
+//**************************************************************************************
+{
+ unsigned int Register;
+ DWORD CurrentThreadId;
+
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint = MainThreadBreakpointList;
+
+ if (BaseAddress == NULL)
+ {
+ 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);
+
+ if (CurrentThreadId == ThreadId)
+ {
+ for (Register = 0; Register < NUMBER_OF_DEBUG_REGISTERS; Register++)
+ {
+ 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;
+}
+
//**************************************************************************************
BOOL SetResumeFlag(PCONTEXT Context)
//**************************************************************************************
@@ -737,6 +1353,82 @@ BOOL ClearSingleStepMode(PCONTEXT Context)
return TRUE;
}
+//**************************************************************************************
+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
+// the breakpoint is restored in ResumeAfterExecutionBreakpoint and execution resumed.
+{
+ PDR7 Dr7;
+
+ if (Context == NULL)
+ return FALSE;
+
+ Dr7 = (PDR7)&(Context->Dr7);
+
+ switch(pBreakpointInfo->Register)
+ {
+ case 0:
+ Dr7->L0 = 0;
+ break;
+ case 1:
+ Dr7->L1 = 0;
+ break;
+ case 2:
+ Dr7->L2 = 0;
+ break;
+ case 3:
+ Dr7->L3 = 0;
+ break;
+ }
+
+ // 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;
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL ResumeAfterExecutionBreakpoint(PCONTEXT Context)
+//**************************************************************************************
+{
+ PDR7 Dr7;
+
+ if (Context == NULL)
+ return FALSE;
+
+ Dr7 = (PDR7)&(Context->Dr7);
+
+ switch(TrapIndex-1)
+ {
+ case 0:
+ Dr7->L0 = 1;
+ break;
+ case 1:
+ Dr7->L1 = 1;
+ break;
+ case 2:
+ Dr7->L2 = 1;
+ break;
+ case 3:
+ Dr7->L3 = 1;
+ break;
+ }
+
+ // Clear the trap flag
+ Context->EFlags &= ~FL_TF;
+
+ // clear the 'trap index'
+ TrapIndex = 0;
+
+ return TRUE;
+}
+
//**************************************************************************************
BOOL ClearDebugRegister
//**************************************************************************************
@@ -746,14 +1438,13 @@ BOOL ClearDebugRegister
int Size,
LPVOID Address,
DWORD Type
-)
-{
+){
CONTEXT Context;
BOOL DoCloseHandle = FALSE;
- PDWORD Dr0 = &Context.Dr0;
- PDWORD Dr1 = &Context.Dr1;
- PDWORD Dr2 = &Context.Dr2;
- PDWORD Dr3 = &Context.Dr3;
+ PDWORD_PTR Dr0 = &Context.Dr0;
+ PDWORD_PTR Dr1 = &Context.Dr1;
+ PDWORD_PTR Dr2 = &Context.Dr2;
+ PDWORD_PTR Dr3 = &Context.Dr3;
PDR7 Dr7 = (PDR7)&(Context.Dr7);
if ((unsigned int)Type > 3)
@@ -774,8 +1465,6 @@ BOOL ClearDebugRegister
return FALSE;
}
- DoOutputDebugString("Clearing breakpoint %i\n", Register);
-
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
if (!GetThreadContext(hThread, &Context))
@@ -813,8 +1502,10 @@ BOOL ClearDebugRegister
Dr7->L3 = 0;
}
- if (Type == BP_READWRITE && address_is_in_stack((DWORD)Address))
+#ifndef _WIN64
+ if (Type == BP_READWRITE && address_is_in_stack((DWORD_PTR)Address))
WoW64UnpatchBreakpoint(Register);
+#endif
Context.Dr6 = 0;
@@ -827,20 +1518,20 @@ BOOL ClearDebugRegister
}
if (DoCloseHandle == TRUE)
- CloseHandle(hThread);
+ CloseHandle(hThread);
return TRUE;
}
//**************************************************************************************
-int CheckExceptionDebugRegister(CONTEXT Context, int Register)
+int ContextCheckDebugRegister(CONTEXT Context, int Register)
//**************************************************************************************
{
PDR7 Dr7;
if (Register < 0 || Register > 3)
{
- DoOutputDebugString("CheckExceptionDebugRegister: %d is an invalid register, must be 0-3.\n", Register);
+ DoOutputDebugString("ContextCheckDebugRegister: %d is an invalid register, must be 0-3.\n", Register);
return FALSE;
}
@@ -896,7 +1587,7 @@ int CheckDebugRegister(HANDLE hThread, int Register)
}
//**************************************************************************************
-BOOL SetExceptionHardwareBreakpoint
+BOOL ContextSetBreakpoint
//**************************************************************************************
(
PCONTEXT Context,
@@ -911,17 +1602,17 @@ BOOL SetExceptionHardwareBreakpoint
if (Register > 3 || Register < 0)
{
- DoOutputDebugString("SetExceptionHardwareBreakpoint: Error - register value %d, can only have value 0-3.\n", Register);
+ DoOutputDebugString("ContextSetBreakpoint: Error - register value %d, can only have value 0-3.\n", Register);
return FALSE;
}
- if (SetExceptionDebugRegister(Context, Register, Size, Address, Type) == FALSE)
+ if (ContextSetDebugRegister(Context, Register, Size, Address, Type) == FALSE)
{
- DoOutputDebugString("Call to SetExceptionDebugRegister failed.\n");
+ DoOutputDebugString("ContextSetBreakpoint: Call to ContextSetDebugRegister failed.\n");
}
else
{
- DoOutputDebugString("Call to SetExceptionDebugRegister succeeded.\n");
+ DoOutputDebugString("ContextSetBreakpoint: Call to ContextSetDebugRegister succeeded.\n");
CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
@@ -931,37 +1622,130 @@ BOOL SetExceptionHardwareBreakpoint
return FALSE;
}
- CurrentThreadBreakpoint->BreakpointInfo[Register].Callback = Callback;
- CurrentThreadBreakpoint->BreakpointInfo[Register].Address = Address;
- CurrentThreadBreakpoint->BreakpointInfo[Register].Size = Size;
- CurrentThreadBreakpoint->BreakpointInfo[Register].Type = Type;
+ CurrentThreadBreakpoint->BreakpointInfo[Register].ThreadHandle = CurrentThreadBreakpoint->ThreadHandle;
+ CurrentThreadBreakpoint->BreakpointInfo[Register].Register = Register;
+ CurrentThreadBreakpoint->BreakpointInfo[Register].Size = Size;
+ CurrentThreadBreakpoint->BreakpointInfo[Register].Address = Address;
+ CurrentThreadBreakpoint->BreakpointInfo[Register].Type = Type;
+ CurrentThreadBreakpoint->BreakpointInfo[Register].Callback = Callback;
}
- return 1;
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL ContextSetNextAvailableBreakpoint
+//**************************************************************************************
+(
+ PCONTEXT Context,
+ unsigned int* Register,
+ int Size,
+ LPVOID Address,
+ DWORD Type,
+ PVOID Callback
+)
+{
+ if (ContextGetNextAvailableBreakpoint(Context, Register) == FALSE)
+ {
+ DoOutputDebugString("ContextSetNextAvailableBreakpoint: ContextGetNextAvailableBreakpoint failed\n");
+ return FALSE;
+ }
+
+ return ContextSetBreakpoint(Context, *Register, Size, Address, Type, Callback);
+}
+
+//**************************************************************************************
+BOOL ContextUpdateCurrentBreakpoint
+//**************************************************************************************
+(
+ PCONTEXT Context,
+ int Size,
+ LPVOID Address,
+ DWORD Type,
+ PVOID Callback
+)
+{
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint;
+ PBREAKPOINTINFO pBreakpointInfo;
+ unsigned int bp;
+
+ CurrentThreadBreakpoint = GetThreadBreakpoints(GetCurrentThreadId());
+
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("ContextUpdateCurrentBreakpoint: Error - Failed to acquire thread breakpoints.\n");
+ return FALSE;
+ }
+
+ for (bp = 0; bp < NUMBER_OF_DEBUG_REGISTERS; bp++)
+ {
+ 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 (bp == 0 && ((DWORD_PTR)pBreakpointInfo->Address == Context->Dr0) && ((DWORD)pBreakpointInfo->Type == ((PDR7)&(Context->Dr7))->RWE0))
+ {
+ return ContextSetBreakpoint(Context, 0, Size, Address, Type, Callback);
+ }
+
+ if (bp == 1 && ((DWORD_PTR)pBreakpointInfo->Address == Context->Dr1) && ((DWORD)pBreakpointInfo->Type == ((PDR7)&(Context->Dr7))->RWE1))
+ {
+ return ContextSetBreakpoint(Context, 1, Size, Address, Type, Callback);
+ }
+
+ if (bp == 2 && ((DWORD_PTR)pBreakpointInfo->Address == Context->Dr2) && ((DWORD)pBreakpointInfo->Type == ((PDR7)&(Context->Dr7))->RWE2))
+ {
+ return ContextSetBreakpoint(Context, 2, Size, Address, Type, Callback);
+ }
+
+ if (bp == 3 && ((DWORD_PTR)pBreakpointInfo->Address == Context->Dr3) && ((DWORD)pBreakpointInfo->Type == ((PDR7)&(Context->Dr7))->RWE3))
+ {
+ return ContextSetBreakpoint(Context, 3, Size, Address, Type, Callback);
+ }
+ }
+ }
+ }
+
+ return FALSE;
}
//**************************************************************************************
DWORD WINAPI SetBreakpointThread(LPVOID lpParam)
//**************************************************************************************
{
+ DWORD RetVal;
+
PBREAKPOINTINFO pBreakpointInfo = (PBREAKPOINTINFO)lpParam;
if (SuspendThread(pBreakpointInfo->ThreadHandle) == 0xFFFFFFFF)
DoOutputErrorString("SetBreakpointThread: Call to SuspendThread failed");
- else
- DoOutputDebugString("SetBreakpointThread: Current thread suspended.\n");
-
- //debug
- DoOutputDebugString("SetBreakpointThread: ABbout to call SetDebugRegister.\n");
if (SetDebugRegister(pBreakpointInfo->ThreadHandle, pBreakpointInfo->Register, pBreakpointInfo->Size, pBreakpointInfo->Address, pBreakpointInfo->Type) == FALSE)
{
- DoOutputErrorString("Call to SetDebugRegister failed");
+ DoOutputErrorString("SetBreakpointThread: Call to SetDebugRegister failed");
}
- DoOutputDebugString("SetBreakpointThread: Breakpoint set, about to resume thread.\n");
-
- ResumeThread(pBreakpointInfo->ThreadHandle);
+ RetVal = ResumeThread(pBreakpointInfo->ThreadHandle);
+ if (RetVal == -1)
+ {
+ DoOutputErrorString("SetBreakpointThread: ResumeThread failed.\n");
+ }
+ else if (RetVal == 0)
+ {
+ DoOutputDebugString("SetBreakpointThread: Error - Sample thread was not suspended.\n");
+ }
+ else if (g_config.debug)
+ {
+ DoOutputDebugString("SetBreakpointThread: Sample thread was suspended, now resumed.\n");
+ }
return 1;
}
@@ -970,29 +1754,88 @@ DWORD WINAPI SetBreakpointThread(LPVOID lpParam)
DWORD WINAPI ClearBreakpointThread(LPVOID lpParam)
//**************************************************************************************
{
+ DWORD RetVal;
PBREAKPOINTINFO pBreakpointInfo = (PBREAKPOINTINFO)lpParam;
- DoOutputDebugString("Inside ClearBreakpointThread.\n");
-
if (SuspendThread(pBreakpointInfo->ThreadHandle) == 0xFFFFFFFF)
DoOutputErrorString("ClearBreakpointThread: Call to SuspendThread failed");
- else
- DoOutputDebugString("ClearBreakpointThread: Current thread suspended.\n");
if (ClearDebugRegister(pBreakpointInfo->ThreadHandle, pBreakpointInfo->Register, pBreakpointInfo->Size, pBreakpointInfo->Address, pBreakpointInfo->Type) == FALSE)
{
DoOutputDebugString("ClearBreakpointThread: Call to ClearDebugRegister failed.\n");
}
- DoOutputDebugString("ClearBreakpointThread: Breakpoint cleared, about to resume thread.\n");
+ RetVal = ResumeThread(pBreakpointInfo->ThreadHandle);
+ if (RetVal == -1)
+ {
+ DoOutputErrorString("ClearBreakpointThread: ResumeThread failed.\n");
+ }
+ else if (RetVal == 0)
+ {
+ DoOutputDebugString("ClearBreakpointThread: Error - Sample thread was not suspended.\n");
+ }
+ else if (g_config.debug)
+ {
+ 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 0x%x.\n", ThreadId);
+ CurrentThreadBreakpoint = CreateThreadBreakpoints(ThreadId);
+ }
+
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("ClearBreakpointWithoutThread: Cannot create new thread breakpoints - FATAL.\n");
+ return FALSE;
+ }
+
+ pBreakpointInfo = &CurrentThreadBreakpoint->BreakpointInfo[Register];
- ResumeThread(pBreakpointInfo->ThreadHandle);
+ if (CurrentThreadBreakpoint->ThreadHandle == NULL)
+ {
+ DoOutputDebugString("ClearBreakpointWithoutThread: There is no thread handle in the thread breakpoint - Error.\n");
+ return FALSE;
+ }
- return 1;
+ if (ClearDebugRegister(pBreakpointInfo->ThreadHandle, pBreakpointInfo->Register, pBreakpointInfo->Size, pBreakpointInfo->Address, pBreakpointInfo->Type) == FALSE)
+ {
+ 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;
}
//**************************************************************************************
-BOOL SetHardwareBreakpoint
+BOOL SetBreakpointWithoutThread
//**************************************************************************************
(
DWORD ThreadId,
@@ -1004,142 +1847,323 @@ BOOL SetHardwareBreakpoint
)
{
PBREAKPOINTINFO pBreakpointInfo;
- PTHREADBREAKPOINTS CurrentThreadBreakpoints;
- HANDLE hSetBreakpointThread;
-
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint;
+ BOOL RetVal;
+
if (Register > 3 || Register < 0)
{
- DoOutputDebugString("SetHardwareBreakpoint: Error - register value %d, can only have value 0-3.\n", Register);
+ DoOutputDebugString("SetBreakpointWithoutThread: Error - register value %d, can only have value 0-3.\n", Register);
return FALSE;
}
- CurrentThreadBreakpoints = GetThreadBreakpoints(ThreadId);
-
- if (CurrentThreadBreakpoints == NULL)
+ CurrentThreadBreakpoint = GetThreadBreakpoints(ThreadId);
+
+ if (CurrentThreadBreakpoint == NULL)
{
- DoOutputDebugString("Creating new thread breakpoints for thread 0x%x.\n", ThreadId);
- CurrentThreadBreakpoints = CreateThreadBreakpoints(ThreadId);
+ DoOutputDebugString("SetBreakpointWithoutThread: Creating new thread breakpoints for thread 0x%x.\n", ThreadId);
+ CurrentThreadBreakpoint = CreateThreadBreakpoints(ThreadId);
}
- if (CurrentThreadBreakpoints == NULL)
+ if (CurrentThreadBreakpoint == NULL)
{
- DoOutputDebugString("Cannot create new thread breakpoints - FATAL.\n");
+ DoOutputDebugString("SetBreakpointWithoutThread: Cannot create new thread breakpoints - FATAL.\n");
return FALSE;
}
- pBreakpointInfo = &CurrentThreadBreakpoints->BreakpointInfo[Register];
+ pBreakpointInfo = &CurrentThreadBreakpoint->BreakpointInfo[Register];
- if (CurrentThreadBreakpoints->ThreadHandle == NULL)
+ if (CurrentThreadBreakpoint->ThreadHandle == NULL)
{
- DoOutputDebugString("SetHardwareBreakpoint: There is no thread handle in the threadbreakpoint!! FATAL ERROR.\n");
+ DoOutputDebugString("SetBreakpointWithoutThread: There is no thread handle in the thread breakpoint - Error.\n");
return FALSE;
}
-
- pBreakpointInfo->ThreadHandle = CurrentThreadBreakpoints->ThreadHandle;
- pBreakpointInfo->Register = Register;
- pBreakpointInfo->Size = Size;
- pBreakpointInfo->Address = Address;
- pBreakpointInfo->Type = Type;
- pBreakpointInfo->Callback = Callback;
-
- OriginalExceptionHandler = SetUnhandledExceptionFilter(CAPEExceptionFilter);
- //AddVectoredContinueHandler(1, CAPEExceptionFilter);
+
+ 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)
+ {
+ DoOutputErrorString("SetBreakpointWithoutThread: Exception calling SetDebugRegister");
+ return FALSE;
+ }
+
+ // Debug
+ DoOutputDebugString("SetBreakpointWithoutThread: bp set with register %d\n", Register);
+
+ return TRUE;
+}
+
+//**************************************************************************************
+BOOL SetBreakpoint
+//**************************************************************************************
+(
+ DWORD ThreadId,
+ int Register,
+ int Size,
+ LPVOID Address,
+ DWORD Type,
+ PVOID Callback
+)
+{
+ //if (DisableThreadSuspend)
+ // return SetBreakpointWithoutThread(ThreadId, Register, Size, Address, Type, Callback);
+
+ PBREAKPOINTINFO pBreakpointInfo;
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint;
+ HANDLE hSetBreakpointThread;
+ DWORD SetBreakpointThreadId;
+ BOOL RetVal;
+
+ if (Register > 3 || Register < 0)
+ {
+ DoOutputDebugString("SetBreakpoint: Error - register value %d, can only have value 0-3.\n", Register);
+ return FALSE;
+ }
- DoOutputDebugString("SetHardwareBreakpoint: about to call SetBreakpointThread\n");
+ CurrentThreadBreakpoint = GetThreadBreakpoints(ThreadId);
- hSetBreakpointThread = CreateThread(
- NULL,
- 0,
- SetBreakpointThread,
- pBreakpointInfo,
- 0,
- &ThreadId);
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("SetBreakpoint: Creating new thread breakpoints for thread 0x%x.\n", ThreadId);
+ CurrentThreadBreakpoint = CreateThreadBreakpoints(ThreadId);
+ }
+
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("SetBreakpoint: Cannot create new thread breakpoints - error.\n");
+ return FALSE;
+ }
- if (hSetBreakpointThread == NULL)
+ pBreakpointInfo = &CurrentThreadBreakpoint->BreakpointInfo[Register];
+
+ if (CurrentThreadBreakpoint->ThreadHandle == NULL)
{
- DoOutputDebugString("Failed to create SetBreakpointThread thread\n");
- return 0;
+ DoOutputDebugString("SetBreakpoint: There is no thread handle in the thread breakpoint - Error.\n");
+ return FALSE;
}
- DoOutputDebugString("SetHardwareBreakpoint: SetBreakpointThread called, beginning wait\n");
+
+ pBreakpointInfo->ThreadHandle = CurrentThreadBreakpoint->ThreadHandle;
+ pBreakpointInfo->Register = Register;
+ pBreakpointInfo->Size = Size;
+ pBreakpointInfo->Address = Address;
+ pBreakpointInfo->Type = Type;
+ pBreakpointInfo->Callback = Callback;
+
+ if (VECTORED_HANDLER)
+ {
+ CAPEExceptionFilterHandle = AddVectoredExceptionHandler(1, CAPEExceptionFilter);
+ OriginalExceptionHandler = NULL;
+ }
+ else
+ {
+ OriginalExceptionHandler = SetUnhandledExceptionFilter(CAPEExceptionFilter);
+ CAPEExceptionFilterHandle = NULL;
+ }
- // Wait until thread has terminated
- WaitForSingleObject(hSetBreakpointThread, INFINITE);
+ __try
+ {
+ hSetBreakpointThread = CreateThread(
+ NULL,
+ 0,
+ SetBreakpointThread,
+ pBreakpointInfo,
+ 0,
+ &SetBreakpointThreadId);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DoOutputErrorString("SetBreakpoint: Unable to create SetBreakpointThread thread");
+ }
- CloseHandle(hSetBreakpointThread);
-
- DoOutputDebugString("SetHardwareBreakpoint: 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);
-
- return 1;
+ if (hSetBreakpointThread)
+ {
+ // 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("SetBreakpoint: SetBreakpointThread timeout, thread killed.\n");
+
+ RetVal = ResumeThread(CurrentThreadBreakpoint->ThreadHandle);
+ if (RetVal == -1)
+ {
+ DoOutputErrorString("SetBreakpoint: ResumeThread failed. About to set breakpoint without thread.\n");
+ }
+ else if (RetVal == 0)
+ {
+ DoOutputDebugString("SetBreakpoint: Sample thread was not suspended. About to set breakpoint without thread.\n");
+ }
+ else
+ {
+ DoOutputDebugString("SetBreakpoint: Sample thread was suspended, now resumed. About to set breakpoint without thread.\n");
+ }
+
+ return SetBreakpointWithoutThread(ThreadId, Register, Size, Address, Type, Callback);
+ }
+
+ DoOutputDebugString("SetBreakpoint: Set bp %d type %d at address 0x%x, size %d with Callback 0x%x, ThreadHandle = 0x%x.\n",
+ pBreakpointInfo->Register,
+ pBreakpointInfo->Type,
+ pBreakpointInfo->Address,
+ pBreakpointInfo->Size,
+ pBreakpointInfo->Callback,
+ pBreakpointInfo->ThreadHandle
+ );
+
+ CloseHandle(hSetBreakpointThread);
+
+ return TRUE;
+ }
+ else
+ {
+ __try
+ {
+ RetVal = SetBreakpointWithoutThread(ThreadId, Register, Size, Address, Type, Callback);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DoOutputErrorString("SetBreakpoint: Error calling SetBreakpointWithoutThread");
+ return FALSE;
+ }
+
+ return RetVal;
+ }
}
//**************************************************************************************
-BOOL ClearHardwareBreakpoint
+BOOL ClearBreakpoint(DWORD ThreadId, int Register)
//**************************************************************************************
-(
- DWORD ThreadId,
- int Register
-)
{
+ return ClearBreakpointWithoutThread(ThreadId, Register);
+/*
PBREAKPOINTINFO pBreakpointInfo;
- PTHREADBREAKPOINTS CurrentThreadBreakpoints;
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint;
HANDLE hClearBreakpointThread;
+ BOOL RetVal;
if (Register > 3 || Register < 0)
{
- DoOutputDebugString("ClearHardwareBreakpoint: Error - register value %d, can only have value 0-3.\n", Register);
+ DoOutputDebugString("ClearBreakpoint: Error - register value %d, can only have value 0-3.\n", Register);
return FALSE;
}
- CurrentThreadBreakpoints = GetThreadBreakpoints(ThreadId);
+ CurrentThreadBreakpoint = GetThreadBreakpoints(ThreadId);
- if (CurrentThreadBreakpoints == NULL)
+ if (CurrentThreadBreakpoint == NULL)
{
DoOutputDebugString("Cannot find thread breakpoints - failed to clear.\n");
return FALSE;
}
- pBreakpointInfo = &CurrentThreadBreakpoints->BreakpointInfo[Register];
+ pBreakpointInfo = &CurrentThreadBreakpoint->BreakpointInfo[Register];
- if (CurrentThreadBreakpoints->ThreadHandle == NULL)
+ if (CurrentThreadBreakpoint->ThreadHandle == NULL)
{
- DoOutputDebugString("ClearHardwareBreakpoint: There is no thread handle in the threadbreakpoint!! FATAL ERROR.\n");
+ DoOutputDebugString("ClearBreakpoint: There is no thread handle in the thread breakpoint - Error.\n");
return FALSE;
}
- else DoOutputDebugString("ClearHardwareBreakpoint: Thread handle 0x%x found in BreakpointInfo struct.\n", CurrentThreadBreakpoints->ThreadHandle);
-
- DoOutputDebugString("About to create ClearBreakpointThread thread\n");
- pBreakpointInfo->ThreadHandle = CurrentThreadBreakpoints->ThreadHandle;
-
- hClearBreakpointThread = CreateThread(NULL, 0, ClearBreakpointThread, pBreakpointInfo, 0, &ThreadId);
+ pBreakpointInfo->ThreadHandle = CurrentThreadBreakpoint->ThreadHandle;
- if (hClearBreakpointThread == NULL)
- {
- DoOutputDebugString("Failed to create ClearBreakpointThread thread\n");
- return 0;
- }
+ __try
+ {
+ hClearBreakpointThread = CreateThread(NULL, 0, ClearBreakpointThread, pBreakpointInfo, 0, &ThreadId);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DoOutputErrorString("ClearBreakpoint: Unable to create ClearBreakpointThread thread");
+ }
- DoOutputDebugString("Successfully created ClearBreakpointThread thread\n");
+ 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");
- // Wait until thread has terminated.
- WaitForSingleObject(hClearBreakpointThread, INFINITE);
+ return ClearBreakpointWithoutThread(ThreadId, Register);
+ }
+
+ DoOutputDebugString("ClearBreakpoint: Cleared breakpoint %d.\n", pBreakpointInfo->Register);
- // Close thread handle and free memory allocations.
- pBreakpointInfo->Register = 0;
+ 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;
- CheckDebugRegisters(pBreakpointInfo->ThreadHandle, 0);
+ return TRUE;
+*/
+}
+
+//**************************************************************************************
+BOOL SetNextAvailableBreakpoint
+//**************************************************************************************
+(
+ DWORD ThreadId,
+ unsigned int* Register,
+ int Size,
+ LPVOID Address,
+ DWORD Type,
+ PVOID Callback
+)
+{
+ PTHREADBREAKPOINTS CurrentThreadBreakpoint = GetThreadBreakpoints(ThreadId);
+
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("SetNextAvailableBreakpoint: Creating new thread breakpoints for thread 0x%x.\n", ThreadId);
+ CurrentThreadBreakpoint = CreateThreadBreakpoints(ThreadId);
+ }
- return 1;
+ if (CurrentThreadBreakpoint == NULL)
+ {
+ DoOutputDebugString("SetNextAvailableBreakpoint: Cannot create new thread breakpoints - FATAL.\n");
+ return FALSE;
+ }
+
+ if (GetNextAvailableBreakpoint(ThreadId, Register) == FALSE)
+ {
+ DoOutputDebugString("SetNextAvailableBreakpoint: GetNextAvailableBreakpoint failed\n");
+ return FALSE;
+ }
+
+ return SetBreakpoint(ThreadId, *Register, Size, Address, Type, Callback);
}
//**************************************************************************************
@@ -1171,19 +2195,41 @@ BOOL InitialiseDebugger(void)
}
// Initialise any global variables
-
+ ChildProcessId = 0;
+ SingleStepHandler = NULL;
+ SampleVectoredHandler = NULL;
+ VECTORED_HANDLER = TRUE;
+
+#ifndef _WIN64
// Ensure wow64 patch is installed if needed
WoW64fix();
+#endif
return TRUE;
}
+//**************************************************************************************
+DWORD_PTR GetNestedStackPointer(void)
+//**************************************************************************************
+{
+ CONTEXT context;
+
+ RtlCaptureContext(&context);
+
+#ifdef _WIN64
+ return (DWORD_PTR)context.Rsp;
+#else
+ return (DWORD_PTR)context.Esp;
+#endif
+}
+
+#ifndef _WIN64
//**************************************************************************************
__declspec (naked dllexport) void DebuggerInit(void)
//**************************************************************************************
{
DWORD StackPointer;
-
+
_asm
{
push ebp
@@ -1194,13 +2240,16 @@ __declspec (naked dllexport) void DebuggerInit(void)
pushad
}
- InitialiseDebugger();
-
-// Target specific code
-
-// End of target specific code
+ DebuggerInitialised = InitialiseDebugger();
+
+// Package specific code
+ GuardPageHandler = (GUARD_PAGE_HANDLER)ExtractionGuardPageHandler;
+// End of package specific code
- DoOutputDebugString("Debugger initialised, about to execute OEP.\n");
+ if (!DebuggerInitialised)
+ DoOutputDebugString("Debugger initialisation failure!\n");
+ else
+ DoOutputDebugString("Debugger initialisation complete, about to execute OEP at 0x%x\n", OEP);
_asm
{
@@ -1209,11 +2258,72 @@ __declspec (naked dllexport) void DebuggerInit(void)
pop ebp
jmp OEP
}
+}
+#else
+#pragma optimize("", off)
+//**************************************************************************************
+void DebuggerInit(void)
+//**************************************************************************************
+{
+ DWORD_PTR StackPointer;
+
+ StackPointer = GetNestedStackPointer() - 8; // this offset has been determined experimentally - TODO: tidy
+
+ DebuggerInitialised = InitialiseDebugger();
+
+// Package specific code
+ GuardPageHandler = (GUARD_PAGE_HANDLER)ExtractionGuardPageHandler;
+// End of package specific code
+
+ if (!DebuggerInitialised)
+ DoOutputDebugString("Debugger initialisation failure!\n");
+ else
+ DoOutputDebugString("Debugger initialisation complete, about to execute OEP at 0x%x\n", OEP);
+
+ OEP();
+}
+#pragma optimize("", on)
+#endif
+
+BOOL SendDebuggerMessage(DWORD Input)
+{
+ BOOL fSuccess;
+ DWORD cbReplyBytes, cbWritten;
+ //struct DEBUGGER_DATA DebuggerData;
+
+ //memset(&DebuggerData, 0, sizeof(struct DEBUGGER_DATA));
+
+ cbReplyBytes = sizeof(DWORD_PTR);
+
+ if (hCapePipe == NULL)
+ {
+ DoOutputErrorString("SendDebuggerMessage: hCapePipe NULL.");
+ return FALSE;
+ }
+
+ // 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
+ );
+
+ 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;
}
//**************************************************************************************
-DWORD WINAPI DebuggerThread(LPVOID lpParam)
+DWORD WINAPI DebuggerLaunch(LPVOID lpParam)
//**************************************************************************************
{
HANDLE hPipe;
@@ -1224,7 +2334,7 @@ DWORD WINAPI DebuggerThread(LPVOID lpParam)
char lpszPipename[MAX_PATH];
OSVERSIONINFO VersionInfo;
- DoOutputDebugString("DebuggerThread: About to connect to CAPEpipe.\n");
+ DoOutputDebugString("DebuggerLaunch: About to connect to CAPEpipe.\n");
memset(lpszPipename, 0, MAX_PATH*sizeof(CHAR));
sprintf_s(lpszPipename, MAX_PATH, "\\\\.\\pipe\\CAPEpipe_%x", GetCurrentProcessId());
@@ -1245,13 +2355,13 @@ DWORD WINAPI DebuggerThread(LPVOID lpParam)
if (GetLastError() != ERROR_PIPE_BUSY)
{
- DoOutputErrorString("Could not open pipe");
+ DoOutputErrorString("DebuggerLaunch: Could not open pipe");
return -1;
}
if (!WaitNamedPipe(lpszPipename, 20))
{
- DoOutputDebugString("Could not open pipe: 20 ms wait timed out.\n");
+ DoOutputDebugString("DebuggerLaunch: Could not open pipe: 20 ms wait timed out.\n");
return -1;
}
}
@@ -1267,7 +2377,7 @@ DWORD WINAPI DebuggerThread(LPVOID lpParam)
);
if (!fSuccess)
{
- DoOutputDebugString("SetNamedPipeHandleState failed.\n");
+ DoOutputDebugString("DebuggerLaunch: SetNamedPipeHandleState failed.\n");
return -1;
}
@@ -1286,36 +2396,67 @@ DWORD WINAPI DebuggerThread(LPVOID lpParam)
);
if (!fSuccess)
{
- DoOutputErrorString("WriteFile to pipe failed");
+ DoOutputErrorString("DebuggerLaunch: WriteFile to pipe failed");
return -1;
}
- DoOutputDebugString("DebuggerInit VA sent to loader: 0x%x\n", FuncAddress);
+ DoOutputDebugString("DebuggerLaunch: DebuggerInit VA sent to loader: 0x%x\n", FuncAddress);
fSuccess = ReadFile(
hPipe,
&OEP,
- sizeof(DWORD),
+ sizeof(DWORD_PTR),
&cbRead,
NULL);
if (!fSuccess && GetLastError() == ERROR_MORE_DATA)
{
- DoOutputDebugString("ReadFile on Pipe: ERROR_MORE_DATA\n");
+ DoOutputDebugString("DebuggerLaunch: ReadFile on Pipe: ERROR_MORE_DATA\n");
CloseHandle(hPipe);
return -1;
}
if (!fSuccess)
{
- DoOutputErrorString("ReadFile from pipe failed");
+ DoOutputErrorString("DebuggerLaunch: ReadFile (OEP) from pipe failed");
CloseHandle(hPipe);
return -1;
}
- DoOutputDebugString("Read OEP from pipe: 0x%x\n", OEP);
+ DoOutputDebugString("DebuggerLaunch: Read OEP from pipe: 0x%x\n", OEP);
- //CloseHandle(hPipe);
+ while (1)
+ {
+ fSuccess = ReadFile(
+ hPipe,
+ &OEP,
+ sizeof(DWORD_PTR),
+ &cbRead,
+ 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");
+ CloseHandle(hPipe);
+ return -1;
+ }
+ else
+ DoOutputDebugString("DebuggerLaunch: Read updated EP from pipe: 0x%x\n", OEP);
+ }
ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFO));
VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
@@ -1326,7 +2467,7 @@ DWORD WINAPI DebuggerThread(LPVOID lpParam)
if (NT5)
{
DoOutputDebugString("NT5: Leaving debugger thread alive.\n");
- while(1)
+ while (1)
{
Sleep(500000);
}
@@ -1353,18 +2494,18 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
if (hProcess == NULL)
{
- DoOutputErrorString("CAPE debug pipe: OpenProcess failed");
+ DoOutputErrorString("DebugNewProcess: OpenProcess failed");
return FALSE;
}
hThread = OpenThread(THREAD_ALL_ACCESS, TRUE, ThreadId);
if (hThread == NULL)
{
- DoOutputErrorString("CAPE debug pipe: OpenThread failed");
+ DoOutputErrorString("DebugNewProcess: OpenThread failed");
return FALSE;
}
- hParentPipe = CreateNamedPipe
+ hCapePipe = CreateNamedPipe
(
lpszPipename,
PIPE_ACCESS_DUPLEX,
@@ -1378,38 +2519,33 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
NULL
);
- if (hParentPipe == INVALID_HANDLE_VALUE)
+ if (hCapePipe == INVALID_HANDLE_VALUE)
{
- DoOutputErrorString("CreateNamedPipe failed");
+ DoOutputErrorString("DebugNewProcess: CreateNamedPipe failed");
return FALSE;
}
-#ifndef STANDALONE
- //pipe("PROCESS:%d:%d,%d", 0, ProcessId, 0); // we need CreateRemoteThread injection
- pipe("PROCESS:%d:%d,%d", (CreationFlags & CREATE_SUSPENDED) ? 1 : 0, ProcessId, ThreadId);
- DoOutputDebugString("DebugNewProcess: Announcing new process to Cuckoo.\n");
-#endif
+ DoOutputDebugString("DebugNewProcess: Announcing new process to Cuckoo, pid: %d\n", ProcessId);
+ pipe("DEBUGGER:%d,%d", ProcessId, ThreadId);
- fConnected = ConnectNamedPipe(hParentPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+ fConnected = ConnectNamedPipe(hCapePipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
fSuccess = FALSE;
cbBytesRead = 0;
if (!fConnected)
{
- DoOutputDebugString("The client could not connect, closing pipe.\n");
-
- CloseHandle(hParentPipe);
-
- return -15;
+ DoOutputDebugString("DebugNewProcess: The client could not connect, closing pipe.\n");
+ CloseHandle(hCapePipe);
+ return FALSE;
}
- DoOutputDebugString("Client connected\n");
+ DoOutputDebugString("DebugNewProcess: Client connected.\n");
fSuccess = ReadFile
(
- hParentPipe,
- &RemoteFuncAddress,
- sizeof(DWORD),
+ hCapePipe,
+ &DebuggerEP,
+ sizeof(DWORD_PTR),
&cbBytesRead,
NULL
);
@@ -1418,36 +2554,40 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
{
if (GetLastError() == ERROR_BROKEN_PIPE)
{
- DoOutputErrorString("Client disconnected.");
+ DoOutputErrorString("DebugNewProcess: Client disconnected.");
}
else
{
- DoOutputErrorString("ReadFile failed.");
+ DoOutputErrorString("DebugNewProcess: ReadFile failed.");
}
}
- if (!RemoteFuncAddress)
+ if (!DebuggerEP)
{
- DoOutputErrorString("Successfully read from pipe, however RemoteFuncAddress = 0.");
+ DoOutputErrorString("DebugNewProcess: Successfully read from pipe, however DebuggerEP = 0.");
return FALSE;
}
Context.ContextFlags = CONTEXT_ALL;
if (!GetThreadContext(hThread, &Context))
{
- DoOutputDebugString("GetThreadContext failed - FATAL\n");
+ DoOutputDebugString("DebugNewProcess: GetThreadContext failed - FATAL\n");
return FALSE;
}
+#ifdef _WIN64
+ OEP = (PVOID)Context.Rcx;
+#else
OEP = (PVOID)Context.Eax;
+#endif
cbWritten = 0;
- cbReplyBytes = sizeof(DWORD);
+ cbReplyBytes = sizeof(DWORD_PTR);
- // Write the reply to the pipe.
+ // Send the OEP to the new process
fSuccess = WriteFile
(
- hParentPipe,
+ hCapePipe,
&OEP,
cbReplyBytes,
&cbWritten,
@@ -1455,7 +2595,7 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
);
if (!fSuccess || cbReplyBytes != cbWritten)
{
- DoOutputErrorString("Failed to send OEP via pipe.");
+ DoOutputErrorString("DebugNewProcess: Failed to send OEP via pipe.");
return FALSE;
}
@@ -1463,17 +2603,24 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
Context.ContextFlags = CONTEXT_ALL;
- Context.Eax = RemoteFuncAddress; // eax holds new entry point
+#ifdef _WIN64
+ Context.Rcx = DebuggerEP; // set the new EP to debugger_init
+#else
+ Context.Eax = DebuggerEP;
+#endif
if (!SetThreadContext(hThread, &Context))
{
- DoOutputDebugString("Failed to set new EP\n");
+ DoOutputDebugString("DebugNewProcess: Failed to set new EP\n");
return FALSE;
}
- DoOutputDebugString("Set new EP to DebuggerInit: 0x%x\n", Context.Eax);
+#ifdef _WIN64
+ DoOutputDebugString("DebugNewProcess: Set new EP to DebuggerInit: 0x%x\n", Context.Rcx);
+#else
+ DoOutputDebugString("DebugNewProcess: Set new EP to DebuggerInit: 0x%x\n", Context.Eax);
+#endif
- //CloseHandle(hParentPipe);
CloseHandle(hProcess);
CloseHandle(hThread);
@@ -1484,31 +2631,35 @@ BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD Creati
int launch_debugger()
//**************************************************************************************
{
- DWORD NewThreadId;
- HANDLE hDebuggerThread;
-
- DoOutputDebugString("CAPE: Launching debugger.\n");
-
- hDebuggerThread = CreateThread(
- NULL,
- 0,
- DebuggerThread,
- NULL,
- 0,
- &NewThreadId);
-
- if (hDebuggerThread == NULL)
+ if (DEBUGGER_LAUNCHER)
{
- DoOutputDebugString("CAPE: Failed to create debug pipe thread.\n");
- return 0;
+ DWORD NewThreadId;
+ HANDLE hDebuggerLaunch;
+
+ hDebuggerLaunch = CreateThread(
+ NULL,
+ 0,
+ DebuggerLaunch,
+ NULL,
+ 0,
+ &NewThreadId);
+
+ if (hDebuggerLaunch == NULL)
+ {
+ DoOutputDebugString("CAPE: Failed to create debugger launch thread.\n");
+ return 0;
+ }
+
+ DoOutputDebugString("CAPE: Launching debugger.\n");
+
+ CloseHandle(hDebuggerLaunch);
+
+ return 1;
}
else
{
- DoOutputDebugString("CAPE: Successfully created debug pipe thread.\n");
+ DebuggerInitialised = InitialiseDebugger();
+
+ return DebuggerInitialised;
}
-
- CloseHandle(hDebuggerThread);
-
- return 1;
-}
-#endif
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/CAPE/Debugger.h b/CAPE/Debugger.h
index d089e41..754cd8b 100644
--- a/CAPE/Debugger.h
+++ b/CAPE/Debugger.h
@@ -1,10 +1,23 @@
#pragma once
+#define DEBUGGER_LAUNCHER 0
+
#define BP_EXEC 0x00
#define BP_WRITE 0x01
#define BP_RESERVED 0x02
#define BP_READWRITE 0x03
+#define EXECUTABLE_FLAGS (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
+
+#define EXTRACTION_MIN_SIZE 0x1001
+
+typedef struct _EXCEPTION_REGISTRATION_RECORD {
+ struct _EXCEPTION_REGISTRATION_RECORD *Next;
+ PEXCEPTION_ROUTINE Handler;
+} EXCEPTION_REGISTRATION_RECORD;
+
+typedef EXCEPTION_REGISTRATION_RECORD *PEXCEPTION_REGISTRATION_RECORD;
+
typedef struct BreakpointInfo
{
HANDLE ThreadHandle;
@@ -25,42 +38,75 @@ typedef struct ThreadBreakpoints
struct ThreadBreakpoints *NextThreadBreakpoints;
} THREADBREAKPOINTS, *PTHREADBREAKPOINTS;
+typedef struct GuardPages
+{
+ PVOID BaseAddress;
+ SIZE_T RegionSize;
+ ULONG Protect;
+ BOOL WriteDetected;
+ PVOID LastWriteAddress;
+ BOOL ReadDetected;
+ PVOID LastReadBy;
+ BOOL PagesDumped;
+ struct GuardPages *NextGuardPages;
+} GUARDPAGES, *PGUARDPAGES;
+
+struct GuardPages *GuardPageList;
+
typedef BOOL (cdecl *SINGLE_STEP_HANDLER)(struct _EXCEPTION_POINTERS*);
+typedef BOOL (cdecl *GUARD_PAGE_HANDLER)(struct _EXCEPTION_POINTERS*);
+typedef BOOL (cdecl *SAMPLE_HANDLER)(struct _EXCEPTION_POINTERS*);
+
+typedef void (WINAPI *PWIN32ENTRY)();
#ifdef __cplusplus
extern "C" {
#endif
-BOOL SetHardwareBreakpoint
-(
- DWORD ThreadId,
- int Register,
- int Size,
- LPVOID Address,
- DWORD Type,
- PVOID Callback
-);
-
-BOOL ClearHardwareBreakpoint(DWORD ThreadId, int Register);
-
-BOOL SetExceptionHardwareBreakpoint
-(
- PCONTEXT Context,
- int Register,
- int Size,
- LPVOID Address,
- DWORD Type,
- PVOID Callback
-);
-
-BOOL ClearExceptionHardwareBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpointInfo);
+BOOL DebuggerInitialised;
+
+void* CAPE_var;
+
+LONG WINAPI CAPEExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo);
+PVOID CAPEExceptionFilterHandle;
+SAMPLE_HANDLER SampleVectoredHandler;
+PEXCEPTION_ROUTINE SEH_TopLevelHandler;
+LPTOP_LEVEL_EXCEPTION_FILTER OriginalExceptionHandler;
+BOOL VECTORED_HANDLER;
+
+DWORD ChildProcessId;
+DWORD ChildThreadId;
+DWORD_PTR DebuggerEP;
+PWIN32ENTRY OEP;
+
+BOOL SetBreakpoint(DWORD ThreadId, int Register, int Size, LPVOID Address, DWORD Type, PVOID Callback);
+BOOL ClearBreakpoint(DWORD ThreadId, int Register);
+BOOL ContextSetBreakpoint(PCONTEXT Context, int Register, int Size, LPVOID Address, DWORD Type, PVOID Callback);
+BOOL GetNextAvailableBreakpoint(DWORD ThreadId, unsigned int* Register);
+BOOL ContextGetNextAvailableBreakpoint(PCONTEXT Context, unsigned int* Register);
+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 ContextSetNextAvailableBreakpoint(PCONTEXT Context, unsigned int* Register, int Size, LPVOID Address, DWORD Type, PVOID Callback);
+BOOL ContextClearBreakpoint(PCONTEXT Context, PBREAKPOINTINFO pBreakpointInfo);
+BOOL ClearBreakpointsInRange(DWORD ThreadId, PVOID BaseAddress, SIZE_T Size);
BOOL SetSingleStepMode(PCONTEXT Context, PVOID Handler);
BOOL ClearSingleStepMode(PCONTEXT Context);
-BOOL ClearAllDebugRegisters(HANDLE hThread);
+BOOL ContextClearAllBreakpoints(PCONTEXT Context);
+BOOL ClearAllBreakpoints(DWORD ThreadId);
BOOL CheckDebugRegisters(HANDLE hThread, PCONTEXT pContext);
+int CheckDebugRegister(HANDLE hThread, int Register);
+int ContextCheckDebugRegister(CONTEXT Context, int Register);
BOOL InitialiseDebugger(void);
BOOL DebugNewProcess(unsigned int ProcessId, unsigned int ThreadId, DWORD CreationFlags);
+BOOL SendDebuggerMessage(DWORD Input);
int launch_debugger(void);
+BOOL IsInGuardPages(PVOID Address);
+PGUARDPAGES GetGuardPages(PVOID Address);
+BOOL DropGuardPages(PGUARDPAGES GuardPages);
+PGUARDPAGES CreateGuardPagess();
+BOOL AddGuardPages(PVOID Address, SIZE_T RegionSize, ULONG Protect);
+BOOL ReinstateGuardPages(PGUARDPAGES GuardPages);
+BOOL DisableGuardPages(PGUARDPAGES GuardPages);
#ifdef __cplusplus
}
diff --git a/CAPE/GetThreadId.c b/CAPE/GetThreadId.c
index 360a104..727bf75 100644
--- a/CAPE/GetThreadId.c
+++ b/CAPE/GetThreadId.c
@@ -117,5 +117,5 @@ DWORD MyGetThreadId
FreeLibrary(hModule);
- return (DWORD)ThreadBasicInfo.ClientId.UniqueThread;
+ return (DWORD)(UINT_PTR)ThreadBasicInfo.ClientId.UniqueThread;
}
diff --git a/CAPE/Output.c b/CAPE/Output.c
index fb805a4..80b7d10 100644
--- a/CAPE/Output.c
+++ b/CAPE/Output.c
@@ -18,13 +18,19 @@ along with this program.If not, see .
#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];
+extern struct CapeMetadata *CapeMetaData;
+extern ULONG_PTR base_of_dll_of_interest;
+
//**************************************************************************************
void DoOutputDebugString(_In_ LPCTSTR lpOutputString, ...)
//**************************************************************************************
@@ -35,11 +41,11 @@ void DoOutputDebugString(_In_ LPCTSTR lpOutputString, ...)
memset(DebugOutput, 0, MAX_PATH*sizeof(TCHAR));
_vsntprintf_s(DebugOutput, MAX_PATH, MAX_PATH, lpOutputString, args);
+#ifdef STANDALONE
OutputDebugString(DebugOutput);
-
+#else
memset(PipeOutput, 0, MAX_PATH*sizeof(TCHAR));
_sntprintf_s(PipeOutput, MAX_PATH, MAX_PATH, "DEBUG:%s", DebugOutput);
-#ifndef STANDALONE
pipe(PipeOutput, strlen(PipeOutput));
#endif
va_end(args);
@@ -72,11 +78,11 @@ void DoOutputErrorString(_In_ LPCTSTR lpOutputString, ...)
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);
+#ifdef STANDALONE
OutputDebugString(ErrorOutput);
-
+#else
memset(PipeOutput, 0, MAX_PATH*sizeof(TCHAR));
_sntprintf_s(PipeOutput, MAX_PATH, MAX_PATH, "DEBUG:%s", ErrorOutput);
-#ifndef STANDALONE
pipe(PipeOutput, strlen(PipeOutput));
#endif
@@ -89,14 +95,134 @@ void DoOutputErrorString(_In_ LPCTSTR lpOutputString, ...)
void CapeOutputFile(_In_ LPCTSTR lpOutputFile)
//**************************************************************************************
{
- memset(DebugOutput, 0, MAX_PATH*sizeof(TCHAR));
- _sntprintf_s(DebugOutput, MAX_PATH, MAX_PATH, "CAPE Output file: %s", lpOutputFile);
- OutputDebugString(DebugOutput);
+ char MetadataPath[MAX_PATH];
+ HANDLE hMetadata;
+ SIZE_T BufferSize;
+ char *Buffer;
+ DWORD dwBytesWritten;
+
+ if (CapeMetaData && CapeMetaData->DumpType == PROCDUMP)
+ {
+ memset(MetadataPath, 0, MAX_PATH * sizeof(TCHAR));
+ _sntprintf_s(MetadataPath, MAX_PATH, MAX_PATH, "%s_info.txt", lpOutputFile);
+ hMetadata = CreateFile(MetadataPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hMetadata == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS)
+ {
+ DoOutputDebugString("CAPE metadata filename exists already: %s", MetadataPath);
+ return;
+ }
+
+ if (hMetadata == INVALID_HANDLE_VALUE)
+ {
+ DoOutputErrorString("Could not create CAPE metadata file");
+ return;
+ }
+
+ BufferSize = 3 * (MAX_PATH + MAX_INT_STRING_LEN + 2) + 2; //// max size string can be
+
+ Buffer = malloc(BufferSize);
+
+ // if our file of interest is a dll, we need to update cape module path now
+ if (base_of_dll_of_interest)
+ {
+ if (g_config.file_of_interest == NULL)
+ {
+ 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, 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);
+
+ if (FALSE == WriteFile(hMetadata, Buffer, strlen(Buffer), &dwBytesWritten, NULL))
+ {
+ DoOutputDebugString("WriteFile error on CAPE metadata file %s\n");
+ CloseHandle(hMetadata);
+ free(Buffer);
+ return;
+ }
+
+ CloseHandle(hMetadata);
+
+ memset(DebugOutput, 0, MAX_PATH*sizeof(TCHAR));
+ _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));
+ _sntprintf_s(PipeOutput, MAX_PATH, MAX_PATH, "FILE_DUMP:%s", lpOutputFile);
+ pipe(PipeOutput, strlen(PipeOutput));
+#endif
- memset(PipeOutput, 0, MAX_PATH*sizeof(TCHAR));
- _sntprintf_s(PipeOutput, MAX_PATH, MAX_PATH, "FILE_CAPE:%s", lpOutputFile);
-#ifndef STANDALONE
- pipe(PipeOutput, strlen(PipeOutput));
+ }
+ else if (CapeMetaData && CapeMetaData->DumpType != PROCDUMP)
+ {
+ memset(MetadataPath, 0, MAX_PATH * sizeof(TCHAR));
+ _sntprintf_s(MetadataPath, MAX_PATH, MAX_PATH, "%s_info.txt", lpOutputFile);
+ hMetadata = CreateFile(MetadataPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hMetadata == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS)
+ {
+ DoOutputDebugString("CAPE metadata filename exists already: %s", MetadataPath);
+ return;
+ }
+
+ if (hMetadata == INVALID_HANDLE_VALUE)
+ {
+ DoOutputErrorString("Could not create CAPE metadata file");
+ return;
+ }
+
+ BufferSize = 3 * (MAX_PATH + MAX_INT_STRING_LEN + 2) + 2; //// max size string can be
+
+ Buffer = malloc(BufferSize);
+
+ CapeMetaData->ModulePath = CapeMetaData->ProcessPath;
+
+ if (CapeMetaData->DumpType == EXTRACTION_PE || CapeMetaData->DumpType == EXTRACTION_SHELLCODE)
+ {
+ // Extraction-specific format
+ _snprintf_s(Buffer, BufferSize, BufferSize, "%d\n%d\n%s\n%s\n0x%x\n", CapeMetaData->DumpType, CapeMetaData->Pid, CapeMetaData->ProcessPath, CapeMetaData->ModulePath, (DWORD)CapeMetaData->Address);
+ }
+ else if (CapeMetaData->DumpType == INJECTION_PE || CapeMetaData->DumpType == INJECTION_SHELLCODE || CapeMetaData->DumpType == EVILGRAB_PAYLOAD || CapeMetaData->DumpType == EVILGRAB_DATA)
+ {
+ if (CapeMetaData->TargetProcess && CapeMetaData->ProcessPath)
+ // Injection-specific format
+ _snprintf_s(Buffer, BufferSize, BufferSize, "%d\n%d\n%s\n%s\n%s\n%d\n", CapeMetaData->DumpType, CapeMetaData->Pid, CapeMetaData->ProcessPath, CapeMetaData->ModulePath, CapeMetaData->TargetProcess, CapeMetaData->TargetPid);
+ }
+ else
+ if (CapeMetaData->ProcessPath)
+ _snprintf_s(Buffer, BufferSize, BufferSize, "%d\n%d\n%s\n%s\n", CapeMetaData->DumpType, CapeMetaData->Pid, CapeMetaData->ProcessPath, CapeMetaData->ModulePath);
+
+ if (FALSE == WriteFile(hMetadata, Buffer, strlen(Buffer), &dwBytesWritten, NULL))
+ {
+ DoOutputDebugString("WriteFile error on CAPE metadata file %s\n");
+ CloseHandle(hMetadata);
+ free(Buffer);
+ return;
+ }
+
+ CloseHandle(hMetadata);
+
+ memset(DebugOutput, 0, MAX_PATH*sizeof(TCHAR));
+ _sntprintf_s(DebugOutput, MAX_PATH, MAX_PATH, "CAPE Output file: %s", lpOutputFile);
+#ifdef STANDALONE
+ OutputDebugString(DebugOutput);
+#else
+ memset(PipeOutput, 0, MAX_PATH*sizeof(TCHAR));
+ _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;
-}
\ No newline at end of file
+}
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/IATSearch.cpp b/CAPE/Scylla/IATSearch.cpp
index f035fa7..4404f3f 100644
--- a/CAPE/Scylla/IATSearch.cpp
+++ b/CAPE/Scylla/IATSearch.cpp
@@ -51,6 +51,7 @@ bool IATSearch::findIATAdvanced( DWORD_PTR startAddress, DWORD_PTR* addressIAT,
#ifdef DEBUG_COMMENTS
DoOutputDebugString("findAPIAddressInIAT2 :: error reading memory");
#endif
+ delete [] dataBuffer;
return false;
}
@@ -277,6 +278,7 @@ bool IATSearch::findIATStartAndSize(DWORD_PTR address, DWORD_PTR * addressIAT, D
#ifdef DEBUG_COMMENTS
DoOutputDebugString("findIATStartAddress :: error reading memory");
#endif
+ delete [] dataBuffer;
return false;
}
diff --git a/CAPE/Scylla/ImportsHandling.cpp b/CAPE/Scylla/ImportsHandling.cpp
index ba791f0..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 75299ed..3c1ee9b 100644
--- a/CAPE/Scylla/ImportsHandling.h
+++ b/CAPE/Scylla/ImportsHandling.h
@@ -1,15 +1,9 @@
#pragma once
+#include
#include