#include "stdafx.h" #include "definitions.h" #include "Global.Breakpoints.h" #include "Global.Debugger.h" #include "Global.Engine.h" #include "Global.Engine.Threading.h" static long engineDefaultBreakPointType = UE_BREAKPOINT_INT3; static BYTE UD2BreakPoint[2] = {0x0F, 0x0B}; static BYTE INT3BreakPoint = 0xCC; static BYTE INT3LongBreakPoint[2] = {0xCD, 0x03}; __declspec(dllexport) void TITCALL SetBPXOptions(long DefaultBreakPointType) { engineDefaultBreakPointType = DefaultBreakPointType; } __declspec(dllexport) bool TITCALL IsBPXEnabled(ULONG_PTR bpxAddress) { MutexLocker lock("BreakPointBuffer"); ULONG_PTR NumberOfBytesReadWritten = 0; DWORD MaximumBreakPoints = 0; BYTE ReadData[10] = {}; int bpcount=BreakPointBuffer.size(); for(int i=0; i> 24; checkBpxType = checkBpxType << 24; if(checkBpxType == UE_BREAKPOINT_TYPE_INT3) { SelectedBreakPointType = UE_BREAKPOINT_INT3; NewBreakPoint.BreakPointSize = 1; bpxDataPrt = &INT3BreakPoint; } else if(checkBpxType == UE_BREAKPOINT_TYPE_LONG_INT3) { SelectedBreakPointType = UE_BREAKPOINT_LONG_INT3; NewBreakPoint.BreakPointSize = 2; bpxDataPrt = &INT3LongBreakPoint; } else if(checkBpxType == UE_BREAKPOINT_TYPE_UD2) { SelectedBreakPointType = UE_BREAKPOINT_UD2; NewBreakPoint.BreakPointSize = 2; bpxDataPrt = &UD2BreakPoint; } } //set breakpoint in process bpxDataCmpPtr = (PMEMORY_COMPARE_HANDLER)bpxDataPrt; VirtualQueryEx(dbgProcessInformation.hProcess, (LPVOID)bpxAddress, &MemInfo, sizeof MEMORY_BASIC_INFORMATION); OldProtect = MemInfo.Protect; VirtualProtectEx(dbgProcessInformation.hProcess, (LPVOID)bpxAddress, NewBreakPoint.BreakPointSize, PAGE_EXECUTE_READWRITE, &OldProtect); if(ReadProcessMemory(dbgProcessInformation.hProcess, (LPVOID)bpxAddress, &NewBreakPoint.OriginalByte[0], NewBreakPoint.BreakPointSize, &NumberOfBytesReadWritten)) { if(WriteProcessMemory(dbgProcessInformation.hProcess, (LPVOID)bpxAddress, bpxDataPrt, NewBreakPoint.BreakPointSize, &NumberOfBytesReadWritten)) { //add new breakpoint to the list NewBreakPoint.AdvancedBreakPointType = SelectedBreakPointType&0xFF; NewBreakPoint.BreakPointActive = UE_BPXACTIVE; NewBreakPoint.BreakPointAddress = bpxAddress; NewBreakPoint.BreakPointType = bpxType&0xFF; NewBreakPoint.ExecuteCallBack = (ULONG_PTR)bpxCallBack; BreakPointBuffer.push_back(NewBreakPoint); VirtualProtectEx(dbgProcessInformation.hProcess, (LPVOID)bpxAddress, NewBreakPoint.BreakPointSize, OldProtect, &OldProtect); return true; } else { VirtualProtectEx(dbgProcessInformation.hProcess, (LPVOID)bpxAddress, NewBreakPoint.BreakPointSize, OldProtect, &OldProtect); return false; } } VirtualProtectEx(dbgProcessInformation.hProcess, (LPVOID)bpxAddress, NewBreakPoint.BreakPointSize, OldProtect, &OldProtect); return false; } __declspec(dllexport) bool TITCALL DeleteBPX(ULONG_PTR bpxAddress) { MutexLocker lock("BreakPointBuffer"); ULONG_PTR NumberOfBytesReadWritten = 0; DWORD OldProtect; int bpcount=BreakPointBuffer.size(); int found=-1; for(int i=0; i NULL) { ReadMemSize = ReadMemSize - (MAXIMUM_INSTRUCTION_SIZE * 10); } if(ReadMemSize == NULL) { VirtualFree(CmdBuffer, NULL, MEM_RELEASE); APIAddress = NULL; } else { tryAPIAddress = (ULONG_PTR)CmdBuffer; } } } } if(hModule != NULL || APIAddress != NULL) { if(hModule != NULL) { APIAddress = (ULONG_PTR)GetProcAddress(hModule, szAPIName); } if(bpxPlace == UE_APIEND) { if(tryAPIAddress == NULL) { tryAPIAddress = APIAddress; } QueryAPIAddress = APIAddress; RtlMoveMemory(&ReadByte, (LPVOID)tryAPIAddress, 1); while(i > 0 && ReadByte != 0xC3 && ReadByte != 0xC2) { if(engineAlowModuleLoading == false && CmdBuffer != NULL) { if(IsBPXEnabled(QueryAPIAddress)) { DisableBPX(QueryAPIAddress); ReadProcessMemory(dbgProcessInformation.hProcess, (void*)APIAddress, CmdBuffer, ReadMemSize, &ueNumberOfReadWrite); RemovedBpx = true; } } currentInstructionLen = StaticLengthDisassemble((LPVOID)tryAPIAddress); tryAPIAddress = tryAPIAddress + currentInstructionLen; RtlMoveMemory(&ReadByte, (LPVOID)tryAPIAddress, 1); QueryAPIAddress = QueryAPIAddress + currentInstructionLen; if(!engineAlowModuleLoading) { if(RemovedBpx) { EnableBPX(QueryAPIAddress - currentInstructionLen); } } RemovedBpx = false; i--; } if(i != NULL) { if((engineAlowModuleLoading == true && ModuleLoaded == true) || (engineAlowModuleLoading == true && ModuleLoaded == false)) { APIAddress = tryAPIAddress; } else if(!engineAlowModuleLoading) { if(CmdBuffer != NULL) { APIAddress = tryAPIAddress - (ULONG_PTR)CmdBuffer + APIAddress; } else { APIAddress = tryAPIAddress; } } } else { if(ModuleLoaded) { FreeLibrary(hModule); } if(CmdBuffer != NULL) { VirtualFree(CmdBuffer, NULL, MEM_RELEASE); } return false; } } if(engineAlowModuleLoading) { APIAddress = (ULONG_PTR)EngineGlobalAPIHandler(dbgProcessInformation.hProcess, NULL, APIAddress, NULL, UE_OPTION_IMPORTER_REALIGN_APIADDRESS); if(ModuleLoaded) { FreeLibrary(hModule); } } else { if(CmdBuffer != NULL) { VirtualFree(CmdBuffer, NULL, MEM_RELEASE); } } return SetBPX(APIAddress, bpxType, bpxCallBack); } else { if(engineAlowModuleLoading) { if(ModuleLoaded) { FreeLibrary(hModule); } } else { if(CmdBuffer != NULL) { VirtualFree(CmdBuffer, NULL, MEM_RELEASE); } } return false; } } else { return false; } return false; } __declspec(dllexport) bool TITCALL DeleteAPIBreakPoint(const char* szDLLName, const char* szAPIName, DWORD bpxPlace) { BYTE ReadByte = NULL; HMODULE hModule = NULL; DWORD ReadMemSize = NULL; ULONG_PTR APIAddress = NULL; ULONG_PTR tryAPIAddress = NULL; ULONG_PTR QueryAPIAddress = NULL; int i = MAX_RET_SEARCH_INSTRUCTIONS; ULONG_PTR ueNumberOfReadWrite = NULL; int currentInstructionLen = NULL; bool ModuleLoaded = false; void* CmdBuffer = NULL; bool RemovedBpx = false; if(szDLLName != NULL && szAPIName != NULL) { hModule = GetModuleHandleA(szDLLName); if(hModule == NULL) { if(engineAlowModuleLoading) { hModule = LoadLibraryA(szDLLName); ModuleLoaded = true; } else { ReadMemSize = MAX_RET_SEARCH_INSTRUCTIONS * MAXIMUM_INSTRUCTION_SIZE; APIAddress = (ULONG_PTR)EngineGlobalAPIHandler(dbgProcessInformation.hProcess, NULL, NULL, szAPIName, UE_OPTION_IMPORTER_RETURN_APIADDRESS); if(APIAddress != NULL) { CmdBuffer = VirtualAlloc(NULL, ReadMemSize, MEM_COMMIT, PAGE_READWRITE); while(ReadProcessMemory(dbgProcessInformation.hProcess, (void*)APIAddress, CmdBuffer, ReadMemSize, &ueNumberOfReadWrite) == false && ReadMemSize > NULL) { ReadMemSize = ReadMemSize - (MAXIMUM_INSTRUCTION_SIZE * 10); } if(ReadMemSize == NULL) { VirtualFree(CmdBuffer, NULL, MEM_RELEASE); APIAddress = NULL; } else { tryAPIAddress = (ULONG_PTR)CmdBuffer; } } } } if(hModule != NULL || APIAddress != NULL) { if(hModule != NULL) { APIAddress = (ULONG_PTR)GetProcAddress(hModule, szAPIName); } if(bpxPlace == UE_APIEND) { if(tryAPIAddress == NULL) { tryAPIAddress = APIAddress; } QueryAPIAddress = APIAddress; RtlMoveMemory(&ReadByte, (LPVOID)tryAPIAddress, 1); while(i > 0 && ReadByte != 0xC3 && ReadByte != 0xC2) { if(engineAlowModuleLoading == false && CmdBuffer != NULL) { if(IsBPXEnabled(QueryAPIAddress)) { DisableBPX(QueryAPIAddress); ReadProcessMemory(dbgProcessInformation.hProcess, (void*)APIAddress, CmdBuffer, ReadMemSize, &ueNumberOfReadWrite); RemovedBpx = true; } } currentInstructionLen = StaticLengthDisassemble((LPVOID)tryAPIAddress); tryAPIAddress = tryAPIAddress + currentInstructionLen; RtlMoveMemory(&ReadByte, (LPVOID)tryAPIAddress, 1); QueryAPIAddress = QueryAPIAddress + currentInstructionLen; if(!engineAlowModuleLoading) { if(RemovedBpx) { EnableBPX(QueryAPIAddress - currentInstructionLen); } } RemovedBpx = false; i--; } if(i != NULL) { if((engineAlowModuleLoading == true && ModuleLoaded == true) || (engineAlowModuleLoading == true && ModuleLoaded == false)) { APIAddress = tryAPIAddress; } else if(!engineAlowModuleLoading) { if(CmdBuffer != NULL) { APIAddress = tryAPIAddress - (ULONG_PTR)CmdBuffer + APIAddress; } else { APIAddress = tryAPIAddress; } } } else { if(ModuleLoaded) { FreeLibrary(hModule); } if(CmdBuffer != NULL) { VirtualFree(CmdBuffer, NULL, MEM_RELEASE); } return false; } } if(engineAlowModuleLoading) { APIAddress = (ULONG_PTR)EngineGlobalAPIHandler(dbgProcessInformation.hProcess, NULL, APIAddress, NULL, UE_OPTION_IMPORTER_REALIGN_APIADDRESS); if(ModuleLoaded) { FreeLibrary(hModule); } } else { if(CmdBuffer != NULL) { VirtualFree(CmdBuffer, NULL, MEM_RELEASE); } } return(DeleteBPX(APIAddress)); } else { if(engineAlowModuleLoading) { if(ModuleLoaded) { FreeLibrary(hModule); } } else { if(CmdBuffer != NULL) { VirtualFree(CmdBuffer, NULL, MEM_RELEASE); } } return false; } } else { return false; } return false; } __declspec(dllexport) bool TITCALL SafeDeleteAPIBreakPoint(const char* szDLLName, const char* szAPIName, DWORD bpxPlace) { //TODO: remove? return DeleteAPIBreakPoint(szDLLName, szAPIName, bpxPlace); } __declspec(dllexport) bool TITCALL SetMemoryBPX(ULONG_PTR MemoryStart, SIZE_T SizeOfMemory, LPVOID bpxCallBack) { return SetMemoryBPXEx(MemoryStart, SizeOfMemory, UE_MEMORY, false, bpxCallBack); } __declspec(dllexport) bool TITCALL SetMemoryBPXEx(ULONG_PTR MemoryStart, SIZE_T SizeOfMemory, DWORD BreakPointType, bool RestoreOnHit, LPVOID bpxCallBack) { MutexLocker lock("BreakPointBuffer"); MEMORY_BASIC_INFORMATION MemInfo; ULONG_PTR NumberOfBytesReadWritten = 0; DWORD NewProtect = 0; DWORD OldProtect = 0; int bpcount=BreakPointBuffer.size(); //search for breakpoint for(int i=0; i-1; i--) { if(BreakPointBuffer.at(i).BreakPointType == UE_BREAKPOINT) { lock.unlock(); DeleteBPX((ULONG_PTR)BreakPointBuffer.at(i).BreakPointAddress); lock.relock(); } else if(BreakPointBuffer.at(i).BreakPointType == UE_MEMORY || BreakPointBuffer.at(i).BreakPointType == UE_MEMORY_READ || BreakPointBuffer.at(i).BreakPointType == UE_MEMORY_WRITE || BreakPointBuffer.at(i).BreakPointType == UE_MEMORY_EXECUTE) { lock.unlock(); RemoveMemoryBPX((ULONG_PTR)BreakPointBuffer.at(i).BreakPointAddress, BreakPointBuffer.at(i).BreakPointSize); lock.relock(); } } DeleteHardwareBreakPoint(UE_DR0); DeleteHardwareBreakPoint(UE_DR1); DeleteHardwareBreakPoint(UE_DR2); DeleteHardwareBreakPoint(UE_DR3); return true; } else if(RemoveOption == UE_OPTION_DISABLEALL) { for(int i=bpcount-1; i>-1; i--) { if(BreakPointBuffer.at(i).BreakPointType == UE_BREAKPOINT && BreakPointBuffer.at(i).BreakPointActive == UE_BPXACTIVE) { lock.unlock(); DisableBPX((ULONG_PTR)BreakPointBuffer.at(i).BreakPointAddress); lock.relock(); } else if(BreakPointBuffer.at(i).BreakPointType == UE_MEMORY || BreakPointBuffer.at(i).BreakPointType == UE_MEMORY_READ || BreakPointBuffer.at(i).BreakPointType == UE_MEMORY_WRITE || BreakPointBuffer.at(i).BreakPointType == UE_MEMORY_EXECUTE) { lock.unlock(); RemoveMemoryBPX((ULONG_PTR)BreakPointBuffer.at(i).BreakPointAddress, BreakPointBuffer.at(i).BreakPointSize); lock.relock(); } } return true; } else if(RemoveOption == UE_OPTION_REMOVEALLDISABLED) { for(int i=bpcount-1; i>-1; i--) { if(BreakPointBuffer.at(i).BreakPointType == UE_BREAKPOINT && BreakPointBuffer.at(i).BreakPointActive == UE_BPXINACTIVE) { lock.unlock(); DeleteBPX((ULONG_PTR)BreakPointBuffer.at(i).BreakPointAddress); lock.relock(); } } return true; } else if(RemoveOption == UE_OPTION_REMOVEALLENABLED) { for(int i=bpcount-1; i>-1; i--) { if(BreakPointBuffer.at(i).BreakPointType == UE_BREAKPOINT && BreakPointBuffer.at(i).BreakPointActive == UE_BPXACTIVE) { lock.unlock(); DeleteBPX((ULONG_PTR)BreakPointBuffer.at(i).BreakPointAddress); lock.relock(); } } return true; } return false; }