mirror of https://github.com/x64dbg/GleeBug
commit
69be313fac
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="AStyleHelper.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
|
||||
<applicationSettings>
|
||||
<AStyleHelper.Properties.Settings>
|
||||
<setting name="Pattern" serializeAs="String">
|
||||
<value>*.c;*.h;*.cpp;*.hpp</value>
|
||||
</setting>
|
||||
<setting name="Options" serializeAs="String">
|
||||
<value>style=allman, convert-tabs, align-pointer=type, align-reference=middle, indent=spaces, indent-namespaces, indent-col1-comments, pad-oper, unpad-paren, keep-one-line-blocks, close-templates</value>
|
||||
</setting>
|
||||
<setting name="Ignore" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="License" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
</AStyleHelper.Properties.Settings>
|
||||
</applicationSettings>
|
||||
</configuration>
|
||||
|
|
@ -75,7 +75,7 @@ namespace GleeBug
|
|||
|
||||
void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance)
|
||||
{
|
||||
if (mThread->isInternalStepping) //handle internal steps
|
||||
if(mThread->isInternalStepping) //handle internal steps
|
||||
{
|
||||
//set internal status
|
||||
mThread->isInternalStepping = false;
|
||||
|
|
@ -84,7 +84,7 @@ namespace GleeBug
|
|||
//call the internal step callback
|
||||
mThread->cbInternalStep();
|
||||
}
|
||||
if (mThread->isSingleStepping) //handle single step
|
||||
if(mThread->isSingleStepping) //handle single step
|
||||
{
|
||||
//set internal status
|
||||
mThread->isSingleStepping = false;
|
||||
|
|
@ -96,7 +96,7 @@ namespace GleeBug
|
|||
//call the user callbacks
|
||||
auto cbStepCopy = mThread->stepCallbacks;
|
||||
mThread->stepCallbacks.clear();
|
||||
for (auto cbStep : cbStepCopy)
|
||||
for(auto cbStep : cbStepCopy)
|
||||
cbStep();
|
||||
}
|
||||
else //handle hardware breakpoint single step exceptions
|
||||
|
|
@ -112,22 +112,22 @@ namespace GleeBug
|
|||
ptr dr6 = registers.Dr6();
|
||||
HardwareSlot breakpointSlot;
|
||||
ptr breakpointAddress;
|
||||
if (exceptionAddress == registers.Dr0() || dr6 & 0x1)
|
||||
if(exceptionAddress == registers.Dr0() || dr6 & 0x1)
|
||||
{
|
||||
breakpointAddress = registers.Dr0();
|
||||
breakpointSlot = HardwareSlot::Dr0;
|
||||
}
|
||||
else if (exceptionAddress == registers.Dr1() || dr6 & 0x2)
|
||||
else if(exceptionAddress == registers.Dr1() || dr6 & 0x2)
|
||||
{
|
||||
breakpointAddress = registers.Dr1();
|
||||
breakpointSlot = HardwareSlot::Dr1;
|
||||
}
|
||||
else if (exceptionAddress == registers.Dr2() || dr6 & 0x4)
|
||||
else if(exceptionAddress == registers.Dr2() || dr6 & 0x4)
|
||||
{
|
||||
breakpointAddress = registers.Dr2();
|
||||
breakpointSlot = HardwareSlot::Dr2;
|
||||
}
|
||||
else if (exceptionAddress == registers.Dr3() || dr6 & 0x8)
|
||||
else if(exceptionAddress == registers.Dr3() || dr6 & 0x8)
|
||||
{
|
||||
breakpointAddress = registers.Dr3();
|
||||
breakpointSlot = HardwareSlot::Dr3;
|
||||
|
|
@ -137,10 +137,10 @@ namespace GleeBug
|
|||
|
||||
//find the breakpoint in the internal structures
|
||||
auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Hardware, breakpointAddress });
|
||||
if (foundInfo == mProcess->breakpoints.end())
|
||||
if(foundInfo == mProcess->breakpoints.end())
|
||||
return; //not a valid hardware breakpoint
|
||||
const auto info = foundInfo->second;
|
||||
if (info.internal.hardware.slot != breakpointSlot)
|
||||
if(info.internal.hardware.slot != breakpointSlot)
|
||||
return; //not a valid hardware breakpoint
|
||||
|
||||
//set continue status
|
||||
|
|
@ -151,7 +151,7 @@ namespace GleeBug
|
|||
mThread->StepInternal(std::bind([this, info]()
|
||||
{
|
||||
//only restore if the breakpoint still exists
|
||||
if (mProcess->breakpoints.find({ BreakpointType::Hardware, info.address }) != mProcess->breakpoints.end())
|
||||
if(mProcess->breakpoints.find({ BreakpointType::Hardware, info.address }) != mProcess->breakpoints.end())
|
||||
mThread->SetHardwareBreakpoint(info.address, info.internal.hardware.slot, info.internal.hardware.type, info.internal.hardware.size);
|
||||
}));
|
||||
|
||||
|
|
@ -160,11 +160,11 @@ namespace GleeBug
|
|||
|
||||
//call the user callback
|
||||
auto foundCallback = mProcess->breakpointCallbacks.find({ BreakpointType::Hardware, info.address });
|
||||
if (foundCallback != mProcess->breakpointCallbacks.end())
|
||||
if(foundCallback != mProcess->breakpointCallbacks.end())
|
||||
foundCallback->second(info);
|
||||
|
||||
//delete the breakpoint if it is singleshoot
|
||||
if (info.singleshoot)
|
||||
if(info.singleshoot)
|
||||
mProcess->DeleteGenericBreakpoint(info);
|
||||
}
|
||||
|
||||
|
|
@ -179,11 +179,11 @@ namespace GleeBug
|
|||
|
||||
//check if the exception address is directly in the range of a memory breakpoint
|
||||
auto foundRange = mProcess->memoryBreakpointRanges.find(Range(exceptionAddress, exceptionAddress));
|
||||
if (foundRange == mProcess->memoryBreakpointRanges.end())
|
||||
if(foundRange == mProcess->memoryBreakpointRanges.end())
|
||||
{
|
||||
//if not in range, check if a memory breakpoint is in the accessed page
|
||||
auto foundPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1));
|
||||
if (foundPage != mProcess->memoryBreakpointPages.end())
|
||||
if(foundPage != mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
//(this means that by our fault the program generated an exception, we should clean it)
|
||||
mContinueStatus = DBG_CONTINUE;
|
||||
|
|
@ -192,7 +192,7 @@ namespace GleeBug
|
|||
const auto pBaseAddr = foundPage->first;
|
||||
|
||||
//We restore the protection
|
||||
if (!mProcess->MemProtect(foundPage->first, PAGE_SIZE, foundPage->second.OldProtect))
|
||||
if(!mProcess->MemProtect(foundPage->first, PAGE_SIZE, foundPage->second.OldProtect))
|
||||
{
|
||||
sprintf_s(error, "MemProtect failed on 0x%p", (void*)foundPage->first);
|
||||
cbInternalError(error);
|
||||
|
|
@ -208,7 +208,7 @@ namespace GleeBug
|
|||
{
|
||||
//seek out the page address
|
||||
auto found_page = mProcess->memoryBreakpointPages.find(pBaseAddr);
|
||||
if (found_page == mProcess->memoryBreakpointPages.end())
|
||||
if(found_page == mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
//no page being used by bpx? Then just return
|
||||
return;
|
||||
|
|
@ -225,7 +225,7 @@ namespace GleeBug
|
|||
exceptionAddress is indeed inside a breakpoint range you have defined.
|
||||
*/
|
||||
auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Memory, foundRange->first });
|
||||
if (foundInfo == mProcess->breakpoints.end())
|
||||
if(foundInfo == mProcess->breakpoints.end())
|
||||
{
|
||||
sprintf_s(error, "inconsistent memory breakpoint at 0x%p", (void*)exceptionAddress);
|
||||
cbInternalError(error);
|
||||
|
|
@ -240,27 +240,26 @@ namespace GleeBug
|
|||
//TODO: check if the right type is accessed (ExceptionInformation[0])
|
||||
//FIXED:
|
||||
auto bpxPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1));
|
||||
auto pageAddr = bpxPage->first;
|
||||
auto pageProperties = bpxPage->second;
|
||||
|
||||
if (bpxPage == mProcess->memoryBreakpointPages.end())
|
||||
if(bpxPage == mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
sprintf_s(error, "Process::memoryBreakPointPages data structure is incosistent, should dump page at 0x%p", (void*)(exceptionAddress & ~(PAGE_SIZE - 1)));
|
||||
cbInternalError(error);
|
||||
return;
|
||||
}
|
||||
auto pageAddr = bpxPage->first;
|
||||
auto pageProperties = bpxPage->second;
|
||||
|
||||
//TODO: If I only have a page with Read bp and the exception was not on read, I don't execute the callback. Because since this was implemented with PAGE_GUARD, writtes or executes still trigger
|
||||
//This callback.
|
||||
//FIX: If the memoryBreakpointPages for this page does not have a access flag and has a read flag, but the exception was not on read. Then we resume the debuggee.
|
||||
if ((exceptionRecord.ExceptionInformation[0] != 0))
|
||||
if((exceptionRecord.ExceptionInformation[0] != 0))
|
||||
{
|
||||
//The bpx is solely on read.
|
||||
if (((pageProperties.Type & 0x2) != 0) && ((pageProperties.Type & 0x1) == 0))
|
||||
if(((pageProperties.Type & 0x2) != 0) && ((pageProperties.Type & 0x1) == 0))
|
||||
{
|
||||
mContinueStatus = DBG_CONTINUE;
|
||||
//We restore the protection
|
||||
if (!mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.OldProtect))
|
||||
if(!mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.OldProtect))
|
||||
{
|
||||
sprintf_s(error, "MemProtect failed on 0x%p", (void*)pageAddr);
|
||||
cbInternalError(error);
|
||||
|
|
@ -270,7 +269,7 @@ namespace GleeBug
|
|||
{
|
||||
//seek out the page address
|
||||
auto found_page = mProcess->memoryBreakpointPages.find(pageAddr);
|
||||
if (found_page == mProcess->memoryBreakpointPages.end())
|
||||
if(found_page == mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
//no page being used by bpx? Then just return
|
||||
return;
|
||||
|
|
@ -280,7 +279,7 @@ namespace GleeBug
|
|||
}));
|
||||
return;
|
||||
}
|
||||
else if (((pageProperties.Type & 0x1) != 0))
|
||||
else if(((pageProperties.Type & 0x1) != 0))
|
||||
{
|
||||
//We are fine if the breakpoint is on Access and somethine other than a read occurred.
|
||||
}
|
||||
|
|
@ -296,7 +295,7 @@ namespace GleeBug
|
|||
{
|
||||
//The generated exception is on read.
|
||||
//If the page doesn't have a breakpoint on read or on access then something else must have gone wrong - we pass execution to debuggee.
|
||||
if ((!(pageProperties.Type & 0x2)) && (!(pageProperties.Type & 0x1)))
|
||||
if((!(pageProperties.Type & 0x2)) && (!(pageProperties.Type & 0x1)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -314,7 +313,7 @@ namespace GleeBug
|
|||
//TODO: execute the user callback (if present)
|
||||
//FIXED:
|
||||
auto bpxCb = mProcess->breakpointCallbacks.find({ BreakpointType::Memory, info.address });
|
||||
if (bpxCb != mProcess->breakpointCallbacks.end())
|
||||
if(bpxCb != mProcess->breakpointCallbacks.end())
|
||||
{
|
||||
bpxCb->second(info);
|
||||
}
|
||||
|
|
@ -323,7 +322,7 @@ namespace GleeBug
|
|||
mContinueStatus = DBG_CONTINUE;
|
||||
//TODO: single step and restore page protection
|
||||
//FIXED:
|
||||
if (!mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.OldProtect))
|
||||
if(!mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.OldProtect))
|
||||
{
|
||||
sprintf_s(error, "MemProtect failed on 0x%p", (void*)pageAddr);
|
||||
cbInternalError(error);
|
||||
|
|
@ -345,14 +344,14 @@ namespace GleeBug
|
|||
//Check if the memory page is mapped
|
||||
|
||||
auto found_page = mProcess->memoryBreakpointPages.find(pageAddr);
|
||||
if (found_page != mProcess->memoryBreakpointPages.end())
|
||||
if(found_page != mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect);
|
||||
}
|
||||
return;
|
||||
}));
|
||||
|
||||
if (info.singleshoot)
|
||||
if(info.singleshoot)
|
||||
{
|
||||
mProcess->DeleteMemoryBreakpoint(exceptionAddress);
|
||||
}
|
||||
|
|
@ -371,11 +370,11 @@ namespace GleeBug
|
|||
|
||||
//check if the exception address is directly in the range of a memory breakpoint
|
||||
auto foundRange = mProcess->memoryBreakpointRanges.find(Range(exceptionAddress, exceptionAddress));
|
||||
if (foundRange == mProcess->memoryBreakpointRanges.end())
|
||||
if(foundRange == mProcess->memoryBreakpointRanges.end())
|
||||
{
|
||||
//if not in range, check if a memory breakpoint is in the accessed page
|
||||
auto foundPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1));
|
||||
if (foundPage != mProcess->memoryBreakpointPages.end())
|
||||
if(foundPage != mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
//(this means that by our fault the program generated an exception, we should clean it)
|
||||
mContinueStatus = DBG_CONTINUE;
|
||||
|
|
@ -384,7 +383,7 @@ namespace GleeBug
|
|||
const auto pBaseAddr = foundPage->first;
|
||||
|
||||
//We restore the protection
|
||||
if (!mProcess->MemProtect(foundPage->first, PAGE_SIZE, foundPage->second.OldProtect))
|
||||
if(!mProcess->MemProtect(foundPage->first, PAGE_SIZE, foundPage->second.OldProtect))
|
||||
{
|
||||
sprintf_s(error, "MemProtect failed on 0x%p", (void*)foundPage->first);
|
||||
cbInternalError(error);
|
||||
|
|
@ -400,7 +399,7 @@ namespace GleeBug
|
|||
{
|
||||
//seek out the page address
|
||||
auto found_page = mProcess->memoryBreakpointPages.find(pBaseAddr);
|
||||
if (found_page == mProcess->memoryBreakpointPages.end())
|
||||
if(found_page == mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
//no page being used by bpx? Then just return
|
||||
return;
|
||||
|
|
@ -417,7 +416,7 @@ namespace GleeBug
|
|||
exceptionAddress is indeed inside a breakpoint range you have defined.
|
||||
*/
|
||||
auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Memory, foundRange->first });
|
||||
if (foundInfo == mProcess->breakpoints.end())
|
||||
if(foundInfo == mProcess->breakpoints.end())
|
||||
{
|
||||
sprintf_s(error, "inconsistent memory breakpoint at 0x%p", (void*)exceptionAddress);
|
||||
cbInternalError(error);
|
||||
|
|
@ -432,7 +431,7 @@ namespace GleeBug
|
|||
//TODO: check if the right type is accessed (ExceptionInformation[0])
|
||||
//FIXED:
|
||||
auto bpxPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1));
|
||||
if (bpxPage == mProcess->memoryBreakpointPages.end())
|
||||
if(bpxPage == mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
sprintf_s(error, "Process::memoryBreakPointPages data structure is incosistent, should dump page at 0x%p", (void*)(exceptionAddress & ~(PAGE_SIZE - 1)));
|
||||
cbInternalError(error);
|
||||
|
|
@ -449,13 +448,13 @@ namespace GleeBug
|
|||
*/
|
||||
//ExceptionInformation[0] should be considered as 1 or 8, because these are for exceptions generated on write or execute.
|
||||
//Execute is only implemented with page guard if no Data-Execution-Prevention is implemented by the Kernel.
|
||||
if ((exceptionRecord.ExceptionInformation[0] == 1) && (!(pageProperties.Type & 4)))
|
||||
if((exceptionRecord.ExceptionInformation[0] == 1) && (!(pageProperties.Type & 4)))
|
||||
{
|
||||
//The exception was on Write but there was no page breakpoint in Write? Then the program changed the page permissions, or naturally overwritten protected data. We do not interfere.
|
||||
return;
|
||||
}
|
||||
|
||||
if ((exceptionRecord.ExceptionInformation[0] == 8) && (!(pageProperties.Type & 8)))
|
||||
if((exceptionRecord.ExceptionInformation[0] == 8) && (!(pageProperties.Type & 8)))
|
||||
{
|
||||
//The exception was on Execution but there was no page breakpoint in Execute? Then the program changed the page permissions, or naturally executed protected code. We do not interfere.
|
||||
return;
|
||||
|
|
@ -470,7 +469,7 @@ namespace GleeBug
|
|||
//TODO: execute the user callback (if present)
|
||||
//FIXED:
|
||||
auto bpxCb = mProcess->breakpointCallbacks.find({ BreakpointType::Memory, info.address });
|
||||
if (bpxCb != mProcess->breakpointCallbacks.end())
|
||||
if(bpxCb != mProcess->breakpointCallbacks.end())
|
||||
{
|
||||
bpxCb->second(info);
|
||||
}
|
||||
|
|
@ -479,7 +478,7 @@ namespace GleeBug
|
|||
mContinueStatus = DBG_CONTINUE;
|
||||
//TODO: single step and restore page protection
|
||||
//FIXED:
|
||||
if (!mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.OldProtect))
|
||||
if(!mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.OldProtect))
|
||||
{
|
||||
sprintf_s(error, "MemProtect failed on 0x%p", (void*)pageAddr);
|
||||
cbInternalError(error);
|
||||
|
|
@ -501,14 +500,14 @@ namespace GleeBug
|
|||
//Check if the memory page is mapped
|
||||
|
||||
auto found_page = mProcess->memoryBreakpointPages.find(pageAddr);
|
||||
if (found_page != mProcess->memoryBreakpointPages.end())
|
||||
if(found_page != mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect);
|
||||
}
|
||||
return;
|
||||
}));
|
||||
|
||||
if (info.singleshoot)
|
||||
if(info.singleshoot)
|
||||
{
|
||||
mProcess->DeleteMemoryBreakpoint(exceptionAddress);
|
||||
}
|
||||
|
|
@ -526,7 +525,7 @@ namespace GleeBug
|
|||
cbExceptionEvent(exceptionInfo);
|
||||
|
||||
//dispatch the exception (https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx)
|
||||
switch (exceptionInfo.ExceptionRecord.ExceptionCode)
|
||||
switch(exceptionInfo.ExceptionRecord.ExceptionCode)
|
||||
{
|
||||
case STATUS_BREAKPOINT:
|
||||
exceptionBreakpoint(exceptionRecord, firstChance);
|
||||
|
|
@ -543,7 +542,7 @@ namespace GleeBug
|
|||
}
|
||||
|
||||
//call the unhandled exception callback
|
||||
if (mContinueStatus == DBG_EXCEPTION_NOT_HANDLED)
|
||||
if(mContinueStatus == DBG_EXCEPTION_NOT_HANDLED)
|
||||
cbUnhandledException(exceptionRecord, firstChance);
|
||||
}
|
||||
};
|
||||
|
|
@ -20,7 +20,8 @@ namespace GleeBug
|
|||
std::make_unique<Process>(createProcess.hProcess,
|
||||
mDebugEvent.dwProcessId,
|
||||
mDebugEvent.dwThreadId,
|
||||
createProcess) });
|
||||
createProcess)
|
||||
});
|
||||
mProcess = mProcesses.find(mDebugEvent.dwProcessId)->second.get();
|
||||
|
||||
//thread housekeeping (main thread is created implicitly)
|
||||
|
|
@ -28,7 +29,8 @@ namespace GleeBug
|
|||
std::make_unique<Thread>(createProcess.hThread,
|
||||
mDebugEvent.dwThreadId,
|
||||
createProcess.lpThreadLocalBase,
|
||||
createProcess.lpStartAddress) });
|
||||
createProcess.lpStartAddress)
|
||||
});
|
||||
mThread = mProcess->thread = mProcess->threads.find(mDebugEvent.dwThreadId)->second.get();
|
||||
|
||||
//call the debug event callback
|
||||
|
|
@ -39,14 +41,14 @@ namespace GleeBug
|
|||
CloseHandle(createProcess.hFile);
|
||||
|
||||
//call attach breakpoint after process creation
|
||||
if (attachBreakpoint)
|
||||
if(attachBreakpoint)
|
||||
cbAttachBreakpoint();
|
||||
}
|
||||
|
||||
void Debugger::exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess)
|
||||
{
|
||||
//check if the terminated process is the main debuggee
|
||||
if (mDebugEvent.dwProcessId == mMainProcess.dwProcessId)
|
||||
if(mDebugEvent.dwProcessId == mMainProcess.dwProcessId)
|
||||
mBreakDebugger = true;
|
||||
|
||||
//call the debug event callback
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ namespace GleeBug
|
|||
std::make_unique<Thread>(createThread.hThread,
|
||||
mDebugEvent.dwThreadId,
|
||||
createThread.lpThreadLocalBase,
|
||||
createThread.lpStartAddress) });
|
||||
createThread.lpStartAddress)
|
||||
});
|
||||
|
||||
//set the current thread
|
||||
mThread = mProcess->thread = mProcess->threads.find(mDebugEvent.dwThreadId)->second.get();
|
||||
|
|
|
|||
|
|
@ -12,38 +12,38 @@ namespace GleeBug
|
|||
mDetachAndBreak = false;
|
||||
|
||||
//use correct WaitForDebugEvent function
|
||||
typedef BOOL(WINAPI *MYWAITFORDEBUGEVENT)(
|
||||
typedef BOOL(WINAPI * MYWAITFORDEBUGEVENT)(
|
||||
_Out_ LPDEBUG_EVENT lpDebugEvent,
|
||||
_In_ DWORD dwMilliseconds
|
||||
);
|
||||
static auto WFDEX = MYWAITFORDEBUGEVENT(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "WaitForDebugEventEx"));
|
||||
static auto MyWaitForDebugEvent = WFDEX ? WFDEX : MYWAITFORDEBUGEVENT(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "WaitForDebugEvent"));
|
||||
if (!MyWaitForDebugEvent)
|
||||
if(!MyWaitForDebugEvent)
|
||||
{
|
||||
cbInternalError("MyWaitForDebugEvent not set!");
|
||||
return;
|
||||
}
|
||||
|
||||
while (!mBreakDebugger)
|
||||
while(!mBreakDebugger)
|
||||
{
|
||||
//wait for a debug event
|
||||
mIsRunning = true;
|
||||
if (!MyWaitForDebugEvent(&mDebugEvent, 100))
|
||||
if(!MyWaitForDebugEvent(&mDebugEvent, 100))
|
||||
{
|
||||
if (mDetach)
|
||||
if(mDetach)
|
||||
{
|
||||
if (!UnsafeDetach())
|
||||
if(!UnsafeDetach())
|
||||
cbInternalError("Debugger::Detach failed!");
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
// Fix based on work by https://github.com/number201724
|
||||
if (WaitForSingleObject(mMainProcess.hProcess, 0) == WAIT_OBJECT_0)
|
||||
if(WaitForSingleObject(mMainProcess.hProcess, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
mDebugEvent.dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT;
|
||||
mDebugEvent.dwProcessId = mMainProcess.dwProcessId;
|
||||
mDebugEvent.dwThreadId = mMainProcess.dwThreadId;
|
||||
if (!GetExitCodeProcess(mMainProcess.hProcess, &mDebugEvent.u.ExitProcess.dwExitCode))
|
||||
if(!GetExitCodeProcess(mMainProcess.hProcess, &mDebugEvent.u.ExitProcess.dwExitCode))
|
||||
mDebugEvent.u.ExitProcess.dwExitCode = 0xFFFFFFFF;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -60,11 +60,11 @@ namespace GleeBug
|
|||
|
||||
//set the current process and thread
|
||||
auto processFound = mProcesses.find(mDebugEvent.dwProcessId);
|
||||
if (processFound != mProcesses.end())
|
||||
if(processFound != mProcesses.end())
|
||||
{
|
||||
mProcess = processFound->second.get();
|
||||
auto threadFound = mProcess->threads.find(mDebugEvent.dwThreadId);
|
||||
if (threadFound != mProcess->threads.end())
|
||||
if(threadFound != mProcess->threads.end())
|
||||
{
|
||||
mThread = mProcess->thread = threadFound->second.get();
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ namespace GleeBug
|
|||
else
|
||||
{
|
||||
mThread = nullptr;
|
||||
if (mProcess)
|
||||
if(mProcess)
|
||||
{
|
||||
mProcess->thread = nullptr;
|
||||
mProcess = nullptr;
|
||||
|
|
@ -87,7 +87,7 @@ namespace GleeBug
|
|||
cbPreDebugEvent(mDebugEvent);
|
||||
|
||||
//dispatch the debug event (documented here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms679302(v=vs.85).aspx)
|
||||
switch (mDebugEvent.dwDebugEventCode)
|
||||
switch(mDebugEvent.dwDebugEventCode)
|
||||
{
|
||||
case CREATE_PROCESS_DEBUG_EVENT:
|
||||
createProcessEvent(mDebugEvent.u.CreateProcessInfo);
|
||||
|
|
@ -125,27 +125,27 @@ namespace GleeBug
|
|||
cbPostDebugEvent(mDebugEvent);
|
||||
|
||||
//execute the delayed-detach
|
||||
if (mDetachAndBreak)
|
||||
if(mDetachAndBreak)
|
||||
{
|
||||
if (!UnsafeDetachAndBreak())
|
||||
if(!UnsafeDetachAndBreak())
|
||||
cbInternalError("Debugger::DetachAndBreak failed!");
|
||||
break;
|
||||
}
|
||||
|
||||
//clear trap flag when set by GleeBug (to prevent an EXCEPTION_SINGLE_STEP after detach)
|
||||
if (mDetach && mThread)
|
||||
if(mDetach && mThread)
|
||||
{
|
||||
if (mThread->isInternalStepping || mThread->isSingleStepping)
|
||||
if(mThread->isInternalStepping || mThread->isSingleStepping)
|
||||
Registers(mThread->hThread, CONTEXT_CONTROL).TrapFlag = false;
|
||||
}
|
||||
|
||||
//continue the debug event
|
||||
if (!ContinueDebugEvent(mDebugEvent.dwProcessId, mDebugEvent.dwThreadId, mContinueStatus))
|
||||
if(!ContinueDebugEvent(mDebugEvent.dwProcessId, mDebugEvent.dwThreadId, mContinueStatus))
|
||||
break;
|
||||
|
||||
if (mDetach || mDetachAndBreak)
|
||||
if(mDetach || mDetachAndBreak)
|
||||
{
|
||||
if (!UnsafeDetach())
|
||||
if(!UnsafeDetach())
|
||||
cbInternalError("Debugger::Detach failed!");
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace GleeBug
|
|||
bool Process::SetBreakpoint(ptr address, bool singleshoot, SoftwareType type)
|
||||
{
|
||||
//check the address
|
||||
if (!MemIsValidPtr(address) ||
|
||||
if(!MemIsValidPtr(address) ||
|
||||
breakpoints.find({ BreakpointType::Software, address }) != breakpoints.end())
|
||||
return false;
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ namespace GleeBug
|
|||
info.type = BreakpointType::Software;
|
||||
|
||||
//determine breakpoint byte and size from the type
|
||||
switch (type)
|
||||
switch(type)
|
||||
{
|
||||
case SoftwareType::ShortInt3:
|
||||
info.internal.software.newbytes[0] = 0xCC;
|
||||
|
|
@ -28,10 +28,10 @@ namespace GleeBug
|
|||
}
|
||||
|
||||
//read/write the breakpoint
|
||||
if (!MemReadUnsafe(address, info.internal.software.oldbytes, info.internal.software.size))
|
||||
if(!MemReadUnsafe(address, info.internal.software.oldbytes, info.internal.software.size))
|
||||
return false;
|
||||
|
||||
if (!MemWriteUnsafe(address, info.internal.software.newbytes, info.internal.software.size))
|
||||
if(!MemWriteUnsafe(address, info.internal.software.newbytes, info.internal.software.size))
|
||||
return false;
|
||||
FlushInstructionCache(hProcess, nullptr, 0);
|
||||
|
||||
|
|
@ -45,10 +45,10 @@ namespace GleeBug
|
|||
bool Process::SetBreakpoint(ptr address, const BreakpointCallback & cbBreakpoint, bool singleshoot, SoftwareType type)
|
||||
{
|
||||
//check if a callback on this address was already found
|
||||
if (breakpointCallbacks.find({ BreakpointType::Software, address }) != breakpointCallbacks.end())
|
||||
if(breakpointCallbacks.find({ BreakpointType::Software, address }) != breakpointCallbacks.end())
|
||||
return false;
|
||||
//set the breakpoint
|
||||
if (!SetBreakpoint(address, singleshoot, type))
|
||||
if(!SetBreakpoint(address, singleshoot, type))
|
||||
return false;
|
||||
//insert the callback
|
||||
breakpointCallbacks.insert({ { BreakpointType::Software, address }, cbBreakpoint });
|
||||
|
|
@ -59,12 +59,12 @@ namespace GleeBug
|
|||
{
|
||||
//find the breakpoint
|
||||
auto found = breakpoints.find({ BreakpointType::Software, address });
|
||||
if (found == breakpoints.end())
|
||||
if(found == breakpoints.end())
|
||||
return false;
|
||||
const auto & info = found->second;
|
||||
|
||||
//restore the breakpoint bytes
|
||||
if (!MemWriteUnsafe(address, info.internal.software.oldbytes, info.internal.software.size))
|
||||
if(!MemWriteUnsafe(address, info.internal.software.oldbytes, info.internal.software.size))
|
||||
return false;
|
||||
FlushInstructionCache(hProcess, nullptr, 0);
|
||||
|
||||
|
|
@ -78,9 +78,9 @@ namespace GleeBug
|
|||
bool Process::GetFreeHardwareBreakpointSlot(HardwareSlot & slot) const
|
||||
{
|
||||
//find a free hardware breakpoint slot
|
||||
for (int i = 0; i < HWBP_COUNT; i++)
|
||||
for(int i = 0; i < HWBP_COUNT; i++)
|
||||
{
|
||||
if (!hardwareBreakpoints[i].internal.hardware.enabled)
|
||||
if(!hardwareBreakpoints[i].internal.hardware.enabled)
|
||||
{
|
||||
slot = HardwareSlot(i);
|
||||
return true;
|
||||
|
|
@ -92,15 +92,15 @@ namespace GleeBug
|
|||
bool Process::SetHardwareBreakpoint(ptr address, HardwareSlot slot, HardwareType type, HardwareSize size, bool singleshoot)
|
||||
{
|
||||
//check the address
|
||||
if (!MemIsValidPtr(address) ||
|
||||
if(!MemIsValidPtr(address) ||
|
||||
breakpoints.find({ BreakpointType::Hardware, address }) != breakpoints.end())
|
||||
return false;
|
||||
|
||||
//attempt to set the hardware breakpoint in every thread
|
||||
bool success = true;
|
||||
for (auto & thread : threads)
|
||||
for(auto & thread : threads)
|
||||
{
|
||||
if (!thread.second->SetHardwareBreakpoint(address, slot, type, size))
|
||||
if(!thread.second->SetHardwareBreakpoint(address, slot, type, size))
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
|
|
@ -108,9 +108,9 @@ namespace GleeBug
|
|||
}
|
||||
|
||||
//if setting failed, unset all
|
||||
if (!success)
|
||||
if(!success)
|
||||
{
|
||||
for (auto & thread : threads)
|
||||
for(auto & thread : threads)
|
||||
thread.second->DeleteHardwareBreakpoint(slot);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -137,10 +137,10 @@ namespace GleeBug
|
|||
bool Process::SetHardwareBreakpoint(ptr address, HardwareSlot slot, const BreakpointCallback & cbBreakpoint, HardwareType type, HardwareSize size, bool singleshoot)
|
||||
{
|
||||
//check if a callback on this address was already found
|
||||
if (breakpointCallbacks.find({ BreakpointType::Hardware, address }) != breakpointCallbacks.end())
|
||||
if(breakpointCallbacks.find({ BreakpointType::Hardware, address }) != breakpointCallbacks.end())
|
||||
return false;
|
||||
//set the hardware breakpoint
|
||||
if (!SetHardwareBreakpoint(address, slot, type, size, singleshoot))
|
||||
if(!SetHardwareBreakpoint(address, slot, type, size, singleshoot))
|
||||
return false;
|
||||
//insert the callback
|
||||
breakpointCallbacks.insert({ { BreakpointType::Hardware, address }, cbBreakpoint });
|
||||
|
|
@ -151,7 +151,7 @@ namespace GleeBug
|
|||
{
|
||||
//find the hardware breakpoint
|
||||
auto found = breakpoints.find({ BreakpointType::Hardware, address });
|
||||
if (found == breakpoints.end())
|
||||
if(found == breakpoints.end())
|
||||
return false;
|
||||
const auto & info = found->second;
|
||||
|
||||
|
|
@ -160,9 +160,9 @@ namespace GleeBug
|
|||
|
||||
//delete the hardware breakpoint from the registers
|
||||
bool success = true;
|
||||
for (auto & thread : threads)
|
||||
for(auto & thread : threads)
|
||||
{
|
||||
if (!thread.second->DeleteHardwareBreakpoint(info.internal.hardware.slot))
|
||||
if(!thread.second->DeleteHardwareBreakpoint(info.internal.hardware.slot))
|
||||
success = false;
|
||||
}
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ namespace GleeBug
|
|||
//These settings can trigger access violation.
|
||||
DWORD dwBase = dwAccess & 0xFF;
|
||||
DWORD dwHigh = dwAccess & 0xFFFFFF00;
|
||||
switch (dwBase)
|
||||
switch(dwBase)
|
||||
{
|
||||
case PAGE_EXECUTE:
|
||||
return dwHigh | PAGE_READONLY;
|
||||
|
|
@ -214,7 +214,7 @@ namespace GleeBug
|
|||
static DWORD RemoveWriteAccess(DWORD dwAccess)
|
||||
{
|
||||
DWORD dwBase = dwAccess & 0xFF;
|
||||
switch (dwBase)
|
||||
switch(dwBase)
|
||||
{
|
||||
case PAGE_READWRITE:
|
||||
case PAGE_EXECUTE_READWRITE:
|
||||
|
|
@ -230,10 +230,10 @@ namespace GleeBug
|
|||
//TODO: handle PAGE_NOACCESS and such correctly (since it cannot be combined with PAGE_GUARD)
|
||||
|
||||
auto found = memoryBreakpointPages.find(page);
|
||||
if (found == memoryBreakpointPages.end())
|
||||
if(found == memoryBreakpointPages.end())
|
||||
{
|
||||
data.Refcount = 1;
|
||||
switch (type)
|
||||
switch(type)
|
||||
{
|
||||
case MemoryType::Access:
|
||||
case MemoryType::Read:
|
||||
|
|
@ -253,13 +253,13 @@ namespace GleeBug
|
|||
data.Type = oldData.Type | uint32(type); //combines new protection
|
||||
data.OldProtect = oldData.OldProtect; // old protection remains the same
|
||||
data.Refcount = oldData.Refcount + 1; //increment reference count
|
||||
if (oldData.Type == uint32(type)) // Edge case for when you need to set a mem bpx on a same page with the same type, you just leave newProtect = OldProtect.
|
||||
if(oldData.Type == uint32(type)) // Edge case for when you need to set a mem bpx on a same page with the same type, you just leave newProtect = OldProtect.
|
||||
{
|
||||
data.NewProtect = data.OldProtect;
|
||||
}
|
||||
else if (data.Type & uint32(MemoryType::Access) || data.Type & uint32(MemoryType::Read)) // Access/Read always becomes PAGE_GUARD ; This page cannot access or Read?
|
||||
else if(data.Type & uint32(MemoryType::Access) || data.Type & uint32(MemoryType::Read)) // Access/Read always becomes PAGE_GUARD ; This page cannot access or Read?
|
||||
data.NewProtect = data.OldProtect | PAGE_GUARD; //as before
|
||||
else if (data.Type & (uint32(MemoryType::Write) | uint32(MemoryType::Execute))) // Write + Execute becomes either PAGE_GUARD or both write and execute flags removed
|
||||
else if(data.Type & (uint32(MemoryType::Write) | uint32(MemoryType::Execute))) // Write + Execute becomes either PAGE_GUARD or both write and execute flags removed
|
||||
data.NewProtect = permanentDep ? RemoveExecuteAccess(RemoveWriteAccess(data.OldProtect)) : data.OldProtect | PAGE_GUARD;
|
||||
}
|
||||
|
||||
|
|
@ -274,12 +274,12 @@ namespace GleeBug
|
|||
//TODO: error reporting
|
||||
|
||||
//basic checks
|
||||
if (!MemIsValidPtr(address) || !size)
|
||||
if(!MemIsValidPtr(address) || !size)
|
||||
return false;
|
||||
|
||||
//check if the range is unused for any previous memory breakpoints
|
||||
auto range = Range(address, address + size - 1);
|
||||
if (memoryBreakpointRanges.find(range) != memoryBreakpointRanges.end())
|
||||
if(memoryBreakpointRanges.find(range) != memoryBreakpointRanges.end())
|
||||
return false;
|
||||
|
||||
//change page protections
|
||||
|
|
@ -297,17 +297,17 @@ namespace GleeBug
|
|||
MemoryBreakpointData data;
|
||||
data.Type = uint32(type);
|
||||
auto alignedAddress = PAGE_ALIGN(address);
|
||||
for (auto page = alignedAddress; page < alignedAddress + ROUND_TO_PAGES(size); page += PAGE_SIZE)
|
||||
for(auto page = alignedAddress; page < alignedAddress + ROUND_TO_PAGES(size); page += PAGE_SIZE)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
if (!VirtualQueryEx(hProcess, LPCVOID(page), &mbi, sizeof(mbi)))
|
||||
if(!VirtualQueryEx(hProcess, LPCVOID(page), &mbi, sizeof(mbi)))
|
||||
{
|
||||
success = false;
|
||||
dprintf("!VirtualQueryEx\n");
|
||||
break;
|
||||
}
|
||||
data.OldProtect = mbi.Protect;
|
||||
if (!SetNewPageProtection(page, data, type))
|
||||
if(!SetNewPageProtection(page, data, type))
|
||||
{
|
||||
success = false;
|
||||
dprintf("!SetNewPageProtection\n");
|
||||
|
|
@ -321,15 +321,15 @@ namespace GleeBug
|
|||
}
|
||||
|
||||
//if changing the page protections failed, attempt to revert all protection changes
|
||||
if (!success)
|
||||
if(!success)
|
||||
{
|
||||
for (const auto & page : breakpointData)
|
||||
for(const auto & page : breakpointData)
|
||||
MemProtect(page.addr, PAGE_SIZE, page.OldProtect);
|
||||
return false;
|
||||
}
|
||||
|
||||
//set the page data
|
||||
for (const auto & page : breakpointData)
|
||||
for(const auto & page : breakpointData)
|
||||
memoryBreakpointPages[page.addr] = page.data;
|
||||
|
||||
//setup the breakpoint information struct
|
||||
|
|
@ -350,10 +350,10 @@ namespace GleeBug
|
|||
bool Process::SetMemoryBreakpoint(ptr address, ptr size, const BreakpointCallback & cbBreakpoint, MemoryType type, bool singleshoot)
|
||||
{
|
||||
//check if a callback on this address was already found
|
||||
if (breakpointCallbacks.find({ BreakpointType::Memory, address }) != breakpointCallbacks.end())
|
||||
if(breakpointCallbacks.find({ BreakpointType::Memory, address }) != breakpointCallbacks.end())
|
||||
return false;
|
||||
//set the memory breakpoint
|
||||
if (!SetMemoryBreakpoint(address, size, type, singleshoot))
|
||||
if(!SetMemoryBreakpoint(address, size, type, singleshoot))
|
||||
return false;
|
||||
//insert the callback
|
||||
breakpointCallbacks.insert({ { BreakpointType::Memory, address }, cbBreakpoint });
|
||||
|
|
@ -369,48 +369,48 @@ namespace GleeBug
|
|||
|
||||
//find the memory breakpoint
|
||||
auto found = breakpoints.find({ BreakpointType::Memory, range->first });
|
||||
if (found == breakpoints.end())
|
||||
if(found == breakpoints.end())
|
||||
return false;
|
||||
const auto & info = found->second;
|
||||
|
||||
//delete the memory breakpoint from the pages
|
||||
bool success = true;
|
||||
auto alignedAddress = PAGE_ALIGN(info.address);
|
||||
for (auto page = alignedAddress; page < alignedAddress + ROUND_TO_PAGES(info.internal.memory.size); page += PAGE_SIZE)
|
||||
for(auto page = alignedAddress; page < alignedAddress + ROUND_TO_PAGES(info.internal.memory.size); page += PAGE_SIZE)
|
||||
{
|
||||
auto foundData = memoryBreakpointPages.find(page);
|
||||
if (foundData == memoryBreakpointPages.end())
|
||||
if(foundData == memoryBreakpointPages.end())
|
||||
continue; //TODO: error reporting
|
||||
auto & data = foundData->second;
|
||||
DWORD Protect;
|
||||
data.Refcount--;
|
||||
if (data.Refcount)
|
||||
if(data.Refcount)
|
||||
{
|
||||
//TODO: properly determine the new protection flag
|
||||
//Are there any other protections left?
|
||||
//If so add the guard
|
||||
if (data.Type & ~uint32(info.internal.memory.type))
|
||||
if(data.Type & ~uint32(info.internal.memory.type))
|
||||
data.NewProtect = data.OldProtect | PAGE_GUARD;
|
||||
Protect = data.NewProtect;
|
||||
}
|
||||
else
|
||||
Protect = data.OldProtect;
|
||||
if (!MemProtect(page, PAGE_SIZE, Protect))
|
||||
if(!MemProtect(page, PAGE_SIZE, Protect))
|
||||
success = false;
|
||||
if (!data.Refcount)
|
||||
if(!data.Refcount)
|
||||
memoryBreakpointPages.erase(foundData);
|
||||
}
|
||||
|
||||
//delete the breakpoint from the maps
|
||||
breakpoints.erase(found);
|
||||
breakpointCallbacks.erase({ BreakpointType::Hardware, address });
|
||||
breakpointCallbacks.erase({ BreakpointType::Memory, address });
|
||||
memoryBreakpointRanges.erase(Range(address, address));
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Process::DeleteGenericBreakpoint(const BreakpointInfo & info)
|
||||
{
|
||||
switch (info.type)
|
||||
switch(info.type)
|
||||
{
|
||||
case BreakpointType::Software:
|
||||
return DeleteBreakpoint(info.address);
|
||||
|
|
|
|||
|
|
@ -6,46 +6,46 @@ namespace GleeBug
|
|||
{
|
||||
//TODO: change page protection if reading failed
|
||||
ptr read;
|
||||
if (!bytesRead)
|
||||
if(!bytesRead)
|
||||
bytesRead = &read;
|
||||
return !!ReadProcessMemory(this->hProcess, reinterpret_cast<const void*>(address), buffer, size, (SIZE_T*)bytesRead);
|
||||
}
|
||||
|
||||
bool Process::MemReadSafe(ptr address, void* buffer, ptr size, ptr* bytesRead) const
|
||||
{
|
||||
if (!MemReadUnsafe(address, buffer, size, bytesRead))
|
||||
if(!MemReadUnsafe(address, buffer, size, bytesRead))
|
||||
return false;
|
||||
|
||||
//choose the filter method that has the lowest cost
|
||||
auto start = address;
|
||||
auto end = start + size;
|
||||
if (size > breakpoints.size())
|
||||
if(size > breakpoints.size())
|
||||
{
|
||||
for (const auto & breakpoint : breakpoints)
|
||||
for(const auto & breakpoint : breakpoints)
|
||||
{
|
||||
if (breakpoint.first.first != BreakpointType::Software)
|
||||
if(breakpoint.first.first != BreakpointType::Software)
|
||||
continue;
|
||||
const auto & info = breakpoint.second;
|
||||
auto curAddress = info.address;
|
||||
for (ptr j = 0; j < info.internal.software.size; j++)
|
||||
for(ptr j = 0; j < info.internal.software.size; j++)
|
||||
{
|
||||
if (curAddress + j >= start && curAddress + j < end)
|
||||
if(curAddress + j >= start && curAddress + j < end)
|
||||
((uint8*)buffer)[curAddress + j - start] = info.internal.software.oldbytes[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ptr i = start; i < end; i++)
|
||||
for(ptr i = start; i < end; i++)
|
||||
{
|
||||
auto found = softwareBreakpointReferences.find(i);
|
||||
if (found == softwareBreakpointReferences.end())
|
||||
if(found == softwareBreakpointReferences.end())
|
||||
continue;
|
||||
const auto & info = found->second->second;
|
||||
auto curAddress = info.address;
|
||||
for (ptr j = 0; j < info.internal.software.size && i < end; j++, i++)
|
||||
for(ptr j = 0; j < info.internal.software.size && i < end; j++, i++)
|
||||
{
|
||||
if (curAddress + j >= start && curAddress + j < end)
|
||||
if(curAddress + j >= start && curAddress + j < end)
|
||||
((uint8*)buffer)[curAddress + j - start] = info.internal.software.oldbytes[j];
|
||||
}
|
||||
i += info.internal.software.size - 1;
|
||||
|
|
@ -58,7 +58,7 @@ namespace GleeBug
|
|||
bool Process::MemWriteUnsafe(ptr address, const void* buffer, ptr size, ptr* bytesWritten)
|
||||
{
|
||||
ptr written;
|
||||
if (!bytesWritten)
|
||||
if(!bytesWritten)
|
||||
bytesWritten = &written;
|
||||
return !!WriteProcessMemory(this->hProcess, reinterpret_cast<void*>(address), buffer, size, (SIZE_T*)bytesWritten);
|
||||
}
|
||||
|
|
@ -79,9 +79,9 @@ namespace GleeBug
|
|||
{
|
||||
DWORD dwOldProtect;
|
||||
auto vps = VirtualProtectEx(hProcess, LPVOID(address), size, newProtect, &dwOldProtect);
|
||||
if (!vps)
|
||||
if(!vps)
|
||||
return false;
|
||||
if (oldProtect)
|
||||
if(oldProtect)
|
||||
*oldProtect = dwOldProtect;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -89,7 +89,7 @@ namespace GleeBug
|
|||
ptr Process::MemFindPattern(ptr data, size_t datasize, const Pattern::WildcardPattern & pattern, bool safe) const
|
||||
{
|
||||
std::vector<uint8> buffer(datasize);
|
||||
if (!MemRead(data, buffer.data(), datasize, nullptr, safe))
|
||||
if(!MemRead(data, buffer.data(), datasize, nullptr, safe))
|
||||
return 0;
|
||||
auto found = Pattern::Find(buffer.data(), datasize, pattern);
|
||||
return found == -1 ? 0 : found + data;
|
||||
|
|
@ -98,7 +98,7 @@ namespace GleeBug
|
|||
ptr Process::MemFindPattern(ptr data, size_t datasize, const uint8* pattern, size_t patternsize, bool safe) const
|
||||
{
|
||||
std::vector<uint8> buffer(datasize);
|
||||
if (!MemRead(data, buffer.data(), datasize, nullptr, safe))
|
||||
if(!MemRead(data, buffer.data(), datasize, nullptr, safe))
|
||||
return 0;
|
||||
auto found = Pattern::Find(buffer.data(), datasize, pattern, patternsize);
|
||||
return found == -1 ? 0 : found + data;
|
||||
|
|
@ -107,7 +107,7 @@ namespace GleeBug
|
|||
bool Process::MemWritePattern(ptr data, size_t datasize, const Pattern::WildcardPattern & pattern, bool safe)
|
||||
{
|
||||
std::vector<uint8> buffer(datasize);
|
||||
if (!MemRead(data, buffer.data(), datasize, nullptr, safe))
|
||||
if(!MemRead(data, buffer.data(), datasize, nullptr, safe))
|
||||
return false;
|
||||
Pattern::Write(buffer.data(), datasize, pattern);
|
||||
return MemWrite(data, buffer.data(), datasize, nullptr, safe);
|
||||
|
|
@ -116,9 +116,9 @@ namespace GleeBug
|
|||
bool Process::MemSearchAndReplace(ptr data, size_t datasize, const Pattern::WildcardPattern & searchpattern, const Pattern::WildcardPattern & replacepattern, bool safe)
|
||||
{
|
||||
std::vector<uint8> buffer(datasize);
|
||||
if (!MemRead(data, buffer.data(), datasize, nullptr, safe))
|
||||
if(!MemRead(data, buffer.data(), datasize, nullptr, safe))
|
||||
return false;
|
||||
if (!Pattern::SearchAndReplace(buffer.data(), datasize, searchpattern, replacepattern))
|
||||
if(!Pattern::SearchAndReplace(buffer.data(), datasize, searchpattern, replacepattern))
|
||||
return false;
|
||||
return MemWrite(data, buffer.data(), datasize, nullptr, safe);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace GleeBug
|
|||
systemBreakpoint(false),
|
||||
permanentDep(false)
|
||||
{
|
||||
for (int i = 0; i < HWBP_COUNT; i++)
|
||||
for(int i = 0; i < HWBP_COUNT; i++)
|
||||
hardwareBreakpoints[i].internal.hardware.enabled = false;
|
||||
}
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ namespace GleeBug
|
|||
{
|
||||
auto gip = Registers(thread->hThread, CONTEXT_CONTROL).Gip();
|
||||
unsigned char data[16];
|
||||
if (MemReadSafe(gip, data, sizeof(data)))
|
||||
if(MemReadSafe(gip, data, sizeof(data)))
|
||||
{
|
||||
ZydisInstructionInfo info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
|
@ -47,7 +47,7 @@ namespace GleeBug
|
|||
stepOver = (info.attributes & repAttributes) != 0;
|
||||
}
|
||||
}
|
||||
if (stepOver)
|
||||
if(stepOver)
|
||||
{
|
||||
SetBreakpoint(gip + info.length, [cbStep](const BreakpointInfo & info)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ namespace GleeBug
|
|||
*/
|
||||
bool MemRead(ptr address, void* buffer, ptr size, ptr* bytesRead = nullptr, bool safe = true) const
|
||||
{
|
||||
if (safe)
|
||||
if(safe)
|
||||
return MemReadSafe(address, buffer, size, bytesRead);
|
||||
return MemRead(address, buffer, size, bytesRead);
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ namespace GleeBug
|
|||
*/
|
||||
bool MemWrite(ptr address, const void* buffer, ptr size, ptr* bytesWritten = nullptr, bool safe = true)
|
||||
{
|
||||
if (safe)
|
||||
if(safe)
|
||||
return MemWriteSafe(address, buffer, size, bytesWritten);
|
||||
return MemWriteUnsafe(address, buffer, size, bytesWritten);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,53 +41,53 @@ namespace GleeBug
|
|||
static ptr dr7_ptr(const DR7 & dr7)
|
||||
{
|
||||
ptr result = 0;
|
||||
if (BITGET(dr7.DR7_MODE[0], 0))
|
||||
if(BITGET(dr7.DR7_MODE[0], 0))
|
||||
BITSET(result, 0);
|
||||
if (BITGET(dr7.DR7_MODE[0], 1))
|
||||
if(BITGET(dr7.DR7_MODE[0], 1))
|
||||
BITSET(result, 1);
|
||||
if (BITGET(dr7.DR7_MODE[1], 0))
|
||||
if(BITGET(dr7.DR7_MODE[1], 0))
|
||||
BITSET(result, 2);
|
||||
if (BITGET(dr7.DR7_MODE[1], 1))
|
||||
if(BITGET(dr7.DR7_MODE[1], 1))
|
||||
BITSET(result, 3);
|
||||
if (BITGET(dr7.DR7_MODE[2], 0))
|
||||
if(BITGET(dr7.DR7_MODE[2], 0))
|
||||
BITSET(result, 4);
|
||||
if (BITGET(dr7.DR7_MODE[2], 1))
|
||||
if(BITGET(dr7.DR7_MODE[2], 1))
|
||||
BITSET(result, 5);
|
||||
if (BITGET(dr7.DR7_MODE[3], 0))
|
||||
if(BITGET(dr7.DR7_MODE[3], 0))
|
||||
BITSET(result, 6);
|
||||
if (BITGET(dr7.DR7_MODE[3], 1))
|
||||
if(BITGET(dr7.DR7_MODE[3], 1))
|
||||
BITSET(result, 7);
|
||||
if (BITGET(dr7.DR7_TYPE[0], 0))
|
||||
if(BITGET(dr7.DR7_TYPE[0], 0))
|
||||
BITSET(result, 16);
|
||||
if (BITGET(dr7.DR7_TYPE[0], 1))
|
||||
if(BITGET(dr7.DR7_TYPE[0], 1))
|
||||
BITSET(result, 17);
|
||||
if (BITGET(dr7.DR7_SIZE[0], 0))
|
||||
if(BITGET(dr7.DR7_SIZE[0], 0))
|
||||
BITSET(result, 18);
|
||||
if (BITGET(dr7.DR7_SIZE[0], 1))
|
||||
if(BITGET(dr7.DR7_SIZE[0], 1))
|
||||
BITSET(result, 19);
|
||||
if (BITGET(dr7.DR7_TYPE[1], 0))
|
||||
if(BITGET(dr7.DR7_TYPE[1], 0))
|
||||
BITSET(result, 20);
|
||||
if (BITGET(dr7.DR7_TYPE[1], 1))
|
||||
if(BITGET(dr7.DR7_TYPE[1], 1))
|
||||
BITSET(result, 21);
|
||||
if (BITGET(dr7.DR7_SIZE[1], 0))
|
||||
if(BITGET(dr7.DR7_SIZE[1], 0))
|
||||
BITSET(result, 22);
|
||||
if (BITGET(dr7.DR7_SIZE[1], 1))
|
||||
if(BITGET(dr7.DR7_SIZE[1], 1))
|
||||
BITSET(result, 23);
|
||||
if (BITGET(dr7.DR7_TYPE[2], 0))
|
||||
if(BITGET(dr7.DR7_TYPE[2], 0))
|
||||
BITSET(result, 24);
|
||||
if (BITGET(dr7.DR7_TYPE[2], 1))
|
||||
if(BITGET(dr7.DR7_TYPE[2], 1))
|
||||
BITSET(result, 25);
|
||||
if (BITGET(dr7.DR7_SIZE[2], 0))
|
||||
if(BITGET(dr7.DR7_SIZE[2], 0))
|
||||
BITSET(result, 26);
|
||||
if (BITGET(dr7.DR7_SIZE[2], 1))
|
||||
if(BITGET(dr7.DR7_SIZE[2], 1))
|
||||
BITSET(result, 27);
|
||||
if (BITGET(dr7.DR7_TYPE[3], 0))
|
||||
if(BITGET(dr7.DR7_TYPE[3], 0))
|
||||
BITSET(result, 28);
|
||||
if (BITGET(dr7.DR7_TYPE[3], 1))
|
||||
if(BITGET(dr7.DR7_TYPE[3], 1))
|
||||
BITSET(result, 29);
|
||||
if (BITGET(dr7.DR7_SIZE[3], 0))
|
||||
if(BITGET(dr7.DR7_SIZE[3], 0))
|
||||
BITSET(result, 30);
|
||||
if (BITGET(dr7.DR7_SIZE[3], 1))
|
||||
if(BITGET(dr7.DR7_SIZE[3], 1))
|
||||
BITSET(result, 31);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -96,60 +96,60 @@ namespace GleeBug
|
|||
{
|
||||
DR7 result;
|
||||
memset(&result, 0, sizeof(DR7));
|
||||
if (BITGET(dr7, 0))
|
||||
if(BITGET(dr7, 0))
|
||||
BITSET(result.DR7_MODE[0], 0);
|
||||
if (BITGET(dr7, 1))
|
||||
if(BITGET(dr7, 1))
|
||||
BITSET(result.DR7_MODE[0], 1);
|
||||
if (BITGET(dr7, 2))
|
||||
if(BITGET(dr7, 2))
|
||||
BITSET(result.DR7_MODE[1], 0);
|
||||
if (BITGET(dr7, 3))
|
||||
if(BITGET(dr7, 3))
|
||||
BITSET(result.DR7_MODE[1], 1);
|
||||
if (BITGET(dr7, 4))
|
||||
if(BITGET(dr7, 4))
|
||||
BITSET(result.DR7_MODE[2], 0);
|
||||
if (BITGET(dr7, 5))
|
||||
if(BITGET(dr7, 5))
|
||||
BITSET(result.DR7_MODE[2], 1);
|
||||
if (BITGET(dr7, 6))
|
||||
if(BITGET(dr7, 6))
|
||||
BITSET(result.DR7_MODE[3], 0);
|
||||
if (BITGET(dr7, 7))
|
||||
if(BITGET(dr7, 7))
|
||||
BITSET(result.DR7_MODE[3], 1);
|
||||
if (BITGET(dr7, 16))
|
||||
if(BITGET(dr7, 16))
|
||||
BITSET(result.DR7_TYPE[0], 0);
|
||||
if (BITGET(dr7, 17))
|
||||
if(BITGET(dr7, 17))
|
||||
BITSET(result.DR7_TYPE[0], 1);
|
||||
if (BITGET(dr7, 18))
|
||||
if(BITGET(dr7, 18))
|
||||
BITSET(result.DR7_SIZE[0], 0);
|
||||
if (BITGET(dr7, 19))
|
||||
if(BITGET(dr7, 19))
|
||||
BITSET(result.DR7_SIZE[0], 1);
|
||||
if (BITGET(dr7, 20))
|
||||
if(BITGET(dr7, 20))
|
||||
BITSET(result.DR7_TYPE[1], 0);
|
||||
if (BITGET(dr7, 21))
|
||||
if(BITGET(dr7, 21))
|
||||
BITSET(result.DR7_TYPE[1], 1);
|
||||
if (BITGET(dr7, 22))
|
||||
if(BITGET(dr7, 22))
|
||||
BITSET(result.DR7_SIZE[1], 0);
|
||||
if (BITGET(dr7, 23))
|
||||
if(BITGET(dr7, 23))
|
||||
BITSET(result.DR7_SIZE[1], 1);
|
||||
if (BITGET(dr7, 24))
|
||||
if(BITGET(dr7, 24))
|
||||
BITSET(result.DR7_TYPE[2], 0);
|
||||
if (BITGET(dr7, 25))
|
||||
if(BITGET(dr7, 25))
|
||||
BITSET(result.DR7_TYPE[2], 1);
|
||||
if (BITGET(dr7, 26))
|
||||
if(BITGET(dr7, 26))
|
||||
BITSET(result.DR7_SIZE[2], 0);
|
||||
if (BITGET(dr7, 27))
|
||||
if(BITGET(dr7, 27))
|
||||
BITSET(result.DR7_SIZE[2], 1);
|
||||
if (BITGET(dr7, 28))
|
||||
if(BITGET(dr7, 28))
|
||||
BITSET(result.DR7_TYPE[3], 0);
|
||||
if (BITGET(dr7, 29))
|
||||
if(BITGET(dr7, 29))
|
||||
BITSET(result.DR7_TYPE[3], 1);
|
||||
if (BITGET(dr7, 30))
|
||||
if(BITGET(dr7, 30))
|
||||
BITSET(result.DR7_SIZE[3], 0);
|
||||
if (BITGET(dr7, 31))
|
||||
if(BITGET(dr7, 31))
|
||||
BITSET(result.DR7_SIZE[3], 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
static DR7_SIZE size_dr7(HardwareSize size)
|
||||
{
|
||||
switch (size)
|
||||
switch(size)
|
||||
{
|
||||
case HardwareSize::SizeByte:
|
||||
return SIZE_1;
|
||||
|
|
@ -168,7 +168,7 @@ namespace GleeBug
|
|||
|
||||
static DR7_TYPE type_dr7(HardwareType type)
|
||||
{
|
||||
switch (type)
|
||||
switch(type)
|
||||
{
|
||||
case HardwareType::Access:
|
||||
return TYPE_READWRITE;
|
||||
|
|
@ -184,13 +184,13 @@ namespace GleeBug
|
|||
bool Thread::SetHardwareBreakpoint(ptr address, HardwareSlot slot, HardwareType type, HardwareSize size)
|
||||
{
|
||||
//check if the alignment is correct
|
||||
if ((address % int(size) != 0))
|
||||
if((address % int(size) != 0))
|
||||
return false;
|
||||
|
||||
Registers registers(hThread, CONTEXT_DEBUG_REGISTERS);
|
||||
|
||||
//set the address register
|
||||
switch (slot)
|
||||
switch(slot)
|
||||
{
|
||||
case HardwareSlot::Dr0:
|
||||
registers.Dr0 = address;
|
||||
|
|
@ -224,7 +224,7 @@ namespace GleeBug
|
|||
Registers registers(hThread, CONTEXT_DEBUG_REGISTERS);
|
||||
|
||||
//zero the address register
|
||||
switch (slot)
|
||||
switch(slot)
|
||||
{
|
||||
case HardwareSlot::Dr0:
|
||||
registers.Dr0 = 0;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ namespace GleeBug
|
|||
{
|
||||
ptr Registers::Get(R reg)
|
||||
{
|
||||
switch (reg)
|
||||
switch(reg)
|
||||
{
|
||||
case R::DR0:
|
||||
return ptr(mContext.Dr0);
|
||||
|
|
@ -258,7 +258,7 @@ namespace GleeBug
|
|||
|
||||
void Registers::Set(R reg, ptr value)
|
||||
{
|
||||
switch (reg)
|
||||
switch(reg)
|
||||
{
|
||||
case R::DR0:
|
||||
mContext.Dr0 = value;
|
||||
|
|
@ -556,7 +556,7 @@ namespace GleeBug
|
|||
|
||||
void Registers::SetFlag(F flag, bool set)
|
||||
{
|
||||
if (set)
|
||||
if(set)
|
||||
mContext.EFlags |= ptr(flag);
|
||||
else
|
||||
mContext.EFlags &= ~ptr(flag);
|
||||
|
|
@ -564,7 +564,7 @@ namespace GleeBug
|
|||
|
||||
void* Registers::getPtr(R reg)
|
||||
{
|
||||
switch (reg)
|
||||
switch(reg)
|
||||
{
|
||||
case R::DR0:
|
||||
return REGPTR(mContext.Dr0);
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ public:
|
|||
Type Get() const
|
||||
{
|
||||
auto ptr = (Type*)mRegisters->getPtr(RegisterIndex);
|
||||
if (ptr)
|
||||
if(ptr)
|
||||
return *ptr;
|
||||
return Type();
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ public:
|
|||
void Set(Type value)
|
||||
{
|
||||
auto ptr = (Type*)mRegisters->getPtr(RegisterIndex);
|
||||
if (ptr)
|
||||
if(ptr)
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ namespace GleeBug
|
|||
{
|
||||
memset(&mContext, 0, sizeof(CONTEXT));
|
||||
mContext.ContextFlags = ContextFlags;
|
||||
if (!!GetThreadContext(hThread, &mContext))
|
||||
if(!!GetThreadContext(hThread, &mContext))
|
||||
{
|
||||
this->hThread = hThread;
|
||||
memcpy(&mOldContext, &mContext, sizeof(CONTEXT));
|
||||
|
|
@ -121,7 +121,7 @@ namespace GleeBug
|
|||
|
||||
Registers::~Registers()
|
||||
{
|
||||
if (hThread && memcmp(&mContext, &mOldContext, sizeof(CONTEXT)) != 0)
|
||||
if(hThread && memcmp(&mContext, &mOldContext, sizeof(CONTEXT)) != 0)
|
||||
SetThreadContext(hThread, &mContext);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ namespace GleeBug
|
|||
StepInto();
|
||||
|
||||
auto target = cbStep.target<void()>();
|
||||
for (const auto & cb : stepCallbacks)
|
||||
for(const auto & cb : stepCallbacks)
|
||||
{
|
||||
if (target == cb.target<void()>())
|
||||
if(target == cb.target<void()>())
|
||||
{
|
||||
puts("duplicate StepInto callback detected!");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace GleeBug
|
|||
const wchar_t* szFileNameCreateProcess;
|
||||
wchar_t* szCommandLineCreateProcess;
|
||||
wchar_t* szCreateWithCmdLine = nullptr;
|
||||
if (szCommandLine == nullptr || !wcslen(szCommandLine))
|
||||
if(szCommandLine == nullptr || !wcslen(szCommandLine))
|
||||
{
|
||||
szCommandLineCreateProcess = nullptr;
|
||||
szFileNameCreateProcess = szFilePath;
|
||||
|
|
@ -87,7 +87,7 @@ namespace GleeBug
|
|||
|
||||
bool Debugger::UnsafeDetachAndBreak()
|
||||
{
|
||||
if (!mProcess || !mThread) //fail when there is no process or thread currently specified
|
||||
if(!mProcess || !mThread) //fail when there is no process or thread currently specified
|
||||
return false;
|
||||
|
||||
//trigger an EXCEPTION_SINGLE_STEP in the debuggee
|
||||
|
|
|
|||
|
|
@ -40,34 +40,34 @@ namespace GleeBug
|
|||
|
||||
bool BufferFile::Read(uint32 offset, void* data, uint32 size, uint32* bytesRead) const
|
||||
{
|
||||
if (offset >= mSize)
|
||||
if(offset >= mSize)
|
||||
return false;
|
||||
auto readSize = size;
|
||||
auto result = true;
|
||||
if (offset + size > mSize)
|
||||
if(offset + size > mSize)
|
||||
{
|
||||
readSize = mSize - offset;
|
||||
result = false;
|
||||
}
|
||||
memcpy(data, (uint8*)mData + offset, readSize);
|
||||
if (bytesRead)
|
||||
if(bytesRead)
|
||||
*bytesRead = readSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BufferFile::Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten)
|
||||
{
|
||||
if (offset >= mSize)
|
||||
if(offset >= mSize)
|
||||
return false;
|
||||
auto writeSize = size;
|
||||
auto result = true;
|
||||
if (offset + size > mSize)
|
||||
if(offset + size > mSize)
|
||||
{
|
||||
writeSize = mSize - offset;
|
||||
result = false;
|
||||
}
|
||||
memcpy((uint8*)mData + offset, data, writeSize);
|
||||
if (bytesWritten)
|
||||
if(bytesWritten)
|
||||
*bytesWritten = writeSize;
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace GleeBug
|
|||
|
||||
void File::Close()
|
||||
{
|
||||
if (IsOpen())
|
||||
if(IsOpen())
|
||||
{
|
||||
CloseHandle(mhFile);
|
||||
mhFile = INVALID_HANDLE_VALUE;
|
||||
|
|
@ -45,30 +45,30 @@ namespace GleeBug
|
|||
|
||||
bool File::Read(uint32 offset, void* data, uint32 size, uint32* bytesRead) const
|
||||
{
|
||||
if (!IsOpen() || SetFilePointer(mhFile, offset, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||
if(!IsOpen() || SetFilePointer(mhFile, offset, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
if (bytesRead)
|
||||
if(bytesRead)
|
||||
*bytesRead = 0;
|
||||
return false;
|
||||
}
|
||||
DWORD NumberOfBytesRead = 0;
|
||||
auto result = !!ReadFile(mhFile, data, size, &NumberOfBytesRead, nullptr);
|
||||
if (bytesRead)
|
||||
if(bytesRead)
|
||||
*bytesRead = uint32(NumberOfBytesRead);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool File::Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten)
|
||||
{
|
||||
if (!IsOpen() || SetFilePointer(mhFile, offset, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||
if(!IsOpen() || SetFilePointer(mhFile, offset, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
if (bytesWritten)
|
||||
if(bytesWritten)
|
||||
*bytesWritten = 0;
|
||||
return false;
|
||||
}
|
||||
DWORD NumberOfBytesWritten = 0;
|
||||
auto result = !!WriteFile(mhFile, data, size, &NumberOfBytesWritten, nullptr);
|
||||
if (bytesWritten)
|
||||
if(bytesWritten)
|
||||
*bytesWritten = uint32(NumberOfBytesWritten);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ namespace GleeBug
|
|||
{
|
||||
//get the access and sharemode flags
|
||||
DWORD access, sharemode;
|
||||
switch (mMode)
|
||||
switch(mMode)
|
||||
{
|
||||
case ReadOnly:
|
||||
access = GENERIC_READ;
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ namespace GleeBug
|
|||
{
|
||||
std::string result;
|
||||
result.reserve(patterntext.length());
|
||||
for (auto ch : patterntext)
|
||||
for(auto ch : patterntext)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f' || ch == '?')
|
||||
if(ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f' || ch == '?')
|
||||
result += ch;
|
||||
}
|
||||
return result;
|
||||
|
|
@ -19,10 +19,10 @@ namespace GleeBug
|
|||
std::vector<Byte> pattern;
|
||||
auto formattext = FormatPattern(patterntext);
|
||||
auto len = formattext.length();
|
||||
if (!len)
|
||||
if(!len)
|
||||
return pattern;
|
||||
|
||||
if (len % 2) //not a multiple of 2
|
||||
if(len % 2) //not a multiple of 2
|
||||
{
|
||||
formattext += '?';
|
||||
len++;
|
||||
|
|
@ -32,20 +32,20 @@ namespace GleeBug
|
|||
|
||||
auto hexChToInt = [](char ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
if(ch >= '0' && ch <= '9')
|
||||
return ch - '0';
|
||||
if (ch >= 'A' && ch <= 'F')
|
||||
if(ch >= 'A' && ch <= 'F')
|
||||
return ch - 'A' + 10;
|
||||
if (ch >= 'a' && ch <= 'f')
|
||||
if(ch >= 'a' && ch <= 'f')
|
||||
return ch - 'a' + 10;
|
||||
return -1;
|
||||
};
|
||||
|
||||
Byte newByte;
|
||||
auto j = 0;
|
||||
for (auto ch : formattext)
|
||||
for(auto ch : formattext)
|
||||
{
|
||||
if (ch == '?') //wildcard
|
||||
if(ch == '?') //wildcard
|
||||
{
|
||||
newByte.nibble[j].wildcard = true; //match anything
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ namespace GleeBug
|
|||
}
|
||||
|
||||
j++;
|
||||
if (j == 2) //two nibbles = one byte
|
||||
if(j == 2) //two nibbles = one byte
|
||||
{
|
||||
j = 0;
|
||||
pattern.push_back(newByte);
|
||||
|
|
@ -72,32 +72,32 @@ namespace GleeBug
|
|||
auto matched = 0;
|
||||
|
||||
unsigned char n1 = (byte >> 4) & 0xF;
|
||||
if (pbyte.nibble[0].wildcard)
|
||||
if(pbyte.nibble[0].wildcard)
|
||||
matched++;
|
||||
else if (pbyte.nibble[0].data == n1)
|
||||
else if(pbyte.nibble[0].data == n1)
|
||||
matched++;
|
||||
|
||||
unsigned char n2 = byte & 0xF;
|
||||
if (pbyte.nibble[1].wildcard)
|
||||
if(pbyte.nibble[1].wildcard)
|
||||
matched++;
|
||||
else if (pbyte.nibble[1].data == n2)
|
||||
else if(pbyte.nibble[1].data == n2)
|
||||
matched++;
|
||||
|
||||
return matched == 2;
|
||||
};
|
||||
|
||||
auto searchpatternsize = pattern.size();
|
||||
if (!searchpatternsize)
|
||||
if(!searchpatternsize)
|
||||
return -1;
|
||||
for (size_t i = 0, pos = 0; i < datasize; i++) //search for the pattern
|
||||
for(size_t i = 0, pos = 0; i < datasize; i++) //search for the pattern
|
||||
{
|
||||
if (MatchByte(data[i], pattern.at(pos))) //check if our pattern matches the current byte
|
||||
if(MatchByte(data[i], pattern.at(pos))) //check if our pattern matches the current byte
|
||||
{
|
||||
pos++;
|
||||
if (pos == searchpatternsize) //everything matched
|
||||
if(pos == searchpatternsize) //everything matched
|
||||
return i - searchpatternsize + 1;
|
||||
}
|
||||
else if (pos > 0) //fix by Computer_Angel
|
||||
else if(pos > 0) //fix by Computer_Angel
|
||||
{
|
||||
i -= pos;
|
||||
pos = 0; //reset current pattern position
|
||||
|
|
@ -108,19 +108,19 @@ namespace GleeBug
|
|||
|
||||
size_t Pattern::Find(const uint8* data, size_t datasize, const uint8* pattern, size_t patternsize)
|
||||
{
|
||||
if (!patternsize)
|
||||
if(!patternsize)
|
||||
return -1;
|
||||
if (patternsize > datasize)
|
||||
if(patternsize > datasize)
|
||||
patternsize = datasize;
|
||||
for (size_t i = 0, pos = 0; i < datasize; i++)
|
||||
for(size_t i = 0, pos = 0; i < datasize; i++)
|
||||
{
|
||||
if (data[i] == pattern[pos])
|
||||
if(data[i] == pattern[pos])
|
||||
{
|
||||
pos++;
|
||||
if (pos == patternsize)
|
||||
if(pos == patternsize)
|
||||
return i - patternsize + 1;
|
||||
}
|
||||
else if (pos > 0)
|
||||
else if(pos > 0)
|
||||
{
|
||||
i -= pos;
|
||||
pos = 0; //reset current pattern position
|
||||
|
|
@ -131,32 +131,32 @@ namespace GleeBug
|
|||
|
||||
void Pattern::Write(uint8* data, size_t datasize, const WildcardPattern & writepattern)
|
||||
{
|
||||
if (!writepattern.size())
|
||||
if(!writepattern.size())
|
||||
return;
|
||||
|
||||
auto writepatternsize = writepattern.size();
|
||||
if (writepatternsize > datasize)
|
||||
if(writepatternsize > datasize)
|
||||
writepatternsize = datasize;
|
||||
|
||||
auto WriteByte = [](uint8* byte, const Byte & pbyte)
|
||||
auto WriteByte = [](uint8 * byte, const Byte & pbyte)
|
||||
{
|
||||
unsigned char n1 = (*byte >> 4) & 0xF;
|
||||
unsigned char n2 = *byte & 0xF;
|
||||
if (!pbyte.nibble[0].wildcard)
|
||||
if(!pbyte.nibble[0].wildcard)
|
||||
n1 = pbyte.nibble[0].data;
|
||||
if (!pbyte.nibble[1].wildcard)
|
||||
if(!pbyte.nibble[1].wildcard)
|
||||
n2 = pbyte.nibble[1].data;
|
||||
*byte = ((n1 << 4) & 0xF0) | (n2 & 0xF);
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < writepatternsize; i++)
|
||||
for(size_t i = 0; i < writepatternsize; i++)
|
||||
WriteByte(&data[i], writepattern.at(i));
|
||||
}
|
||||
|
||||
bool Pattern::SearchAndReplace(uint8* data, size_t datasize, const WildcardPattern & searchpattern, const WildcardPattern & replacepattern)
|
||||
{
|
||||
auto found = Find(data, datasize, searchpattern);
|
||||
if (found == -1)
|
||||
if(found == -1)
|
||||
return false;
|
||||
Write(data + found, datasize - found, replacepattern);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -49,24 +49,24 @@ namespace GleeBug
|
|||
|
||||
//read the DOS header
|
||||
mDosHeader = readRegion<IMAGE_DOS_HEADER>();
|
||||
if (!mDosHeader)
|
||||
if(!mDosHeader)
|
||||
return ErrorDosHeaderRead;
|
||||
|
||||
//verify the DOS header
|
||||
if (mDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
if(mDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return ErrorDosHeaderMagic;
|
||||
|
||||
//get the NT headers offset
|
||||
auto newOffset = mDosHeader->e_lfanew;
|
||||
|
||||
//verify the new offset
|
||||
if (newOffset < 0 || uint32(newOffset) >= mFile.GetSize())
|
||||
if(newOffset < 0 || uint32(newOffset) >= mFile.GetSize())
|
||||
return ErrorDosHeaderNtHeaderOffset;
|
||||
|
||||
//special case where DOS and PE header overlap (tinygui.exe)
|
||||
if (uint32(newOffset) < mOffset)
|
||||
if(uint32(newOffset) < mOffset)
|
||||
{
|
||||
if (!allowOverlap)
|
||||
if(!allowOverlap)
|
||||
return ErrorDosHeaderNtHeaderOffsetOverlap;
|
||||
|
||||
mDosNtOverlap = true;
|
||||
|
|
@ -80,38 +80,38 @@ namespace GleeBug
|
|||
mAfterDosData = readRegion<uint8>(afterDosCount);
|
||||
}
|
||||
|
||||
if (!mAfterDosData)
|
||||
if(!mAfterDosData)
|
||||
return ErrorAfterDosHeaderData;
|
||||
|
||||
//read & verify the signature
|
||||
auto signature = readRegion<DWORD>();
|
||||
if (!signature)
|
||||
if(!signature)
|
||||
return ErrorNtSignatureRead;
|
||||
if (*signature() != IMAGE_NT_SIGNATURE)
|
||||
if(*signature() != IMAGE_NT_SIGNATURE)
|
||||
return ErrorNtSignatureMagic;
|
||||
|
||||
//read the file header
|
||||
auto ifh = readRegion<IMAGE_FILE_HEADER>();
|
||||
if (!ifh)
|
||||
if(!ifh)
|
||||
return ErrorNtFileHeaderRead;
|
||||
|
||||
//read the optional header
|
||||
uint32 realSizeOfIoh;
|
||||
switch (ifh->Machine)
|
||||
switch(ifh->Machine)
|
||||
{
|
||||
case IMAGE_FILE_MACHINE_I386:
|
||||
{
|
||||
//read & verify the optional header
|
||||
realSizeOfIoh = uint32(sizeof(IMAGE_OPTIONAL_HEADER32));
|
||||
auto ioh = readRegion<IMAGE_OPTIONAL_HEADER32>();
|
||||
if (!ioh) //TODO: support truncated optional header (tinyXP.exe)
|
||||
if(!ioh) //TODO: support truncated optional header (tinyXP.exe)
|
||||
return ErrorNtOptionalHeaderRead;
|
||||
if (ioh->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
if(ioh->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
return ErrorNtOptionalHeaderMagic;
|
||||
|
||||
//construct & verify the NT headers region
|
||||
mNtHeaders32 = Region<IMAGE_NT_HEADERS32>(&mData, signature.Offset());
|
||||
if (!mNtHeaders32)
|
||||
if(!mNtHeaders32)
|
||||
return ErrorNtHeadersRegionSize;
|
||||
}
|
||||
break;
|
||||
|
|
@ -123,14 +123,14 @@ namespace GleeBug
|
|||
//read & verify the optional header
|
||||
realSizeOfIoh = uint32(sizeof(IMAGE_OPTIONAL_HEADER64));
|
||||
auto ioh = readRegion<IMAGE_OPTIONAL_HEADER64>();
|
||||
if (!ioh)
|
||||
if(!ioh)
|
||||
return ErrorNtOptionalHeaderRead;
|
||||
if (ioh->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||
if(ioh->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||
return ErrorNtOptionalHeaderMagic;
|
||||
|
||||
//construct & verify the NT headers region
|
||||
mNtHeaders64 = Region<IMAGE_NT_HEADERS64>(&mData, signature.Offset());
|
||||
if (!mNtHeaders64)
|
||||
if(!mNtHeaders64)
|
||||
return ErrorNtHeadersRegionSize;
|
||||
}
|
||||
break;
|
||||
|
|
@ -139,11 +139,11 @@ namespace GleeBug
|
|||
{
|
||||
//try the best possible effort (corkami's d_resource.dll)
|
||||
auto ioh = readRegion<uint8>(ifh->SizeOfOptionalHeader);
|
||||
if (!ioh)
|
||||
if(!ioh)
|
||||
return ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead;
|
||||
|
||||
mNtHeaders32 = Region<IMAGE_NT_HEADERS32>(&mData, signature.Offset());
|
||||
if (!mNtHeaders32)
|
||||
if(!mNtHeaders32)
|
||||
return ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize;
|
||||
|
||||
return ErrorNtFileHeaderUnsupportedMachine;
|
||||
|
|
@ -154,23 +154,23 @@ namespace GleeBug
|
|||
|
||||
//check the SizeOfOptionalHeader field
|
||||
auto sizeOfIoh = ifh->SizeOfOptionalHeader;
|
||||
if (numberOfSections && sizeOfIoh < realSizeOfIoh) //TODO: this can be valid in certain circumstances (nullSOH-XP)
|
||||
if(numberOfSections && sizeOfIoh < realSizeOfIoh) //TODO: this can be valid in certain circumstances (nullSOH-XP)
|
||||
return ErrorNtFileHeaderSizeOfOptionalHeaderOverlap;
|
||||
|
||||
//read data after the optional header (TODO: check if this is even possible)
|
||||
uint32 afterOptionalSize = realSizeOfIoh < sizeOfIoh ? sizeOfIoh - realSizeOfIoh : 0;
|
||||
mAfterOptionalData = readRegion<uint8>(afterOptionalSize);
|
||||
if (!mAfterOptionalData)
|
||||
if(!mAfterOptionalData)
|
||||
return ErrorAfterOptionalHeaderDataRead;
|
||||
|
||||
//read the section headers
|
||||
mSectionHeaders = readRegion<IMAGE_SECTION_HEADER>(numberOfSections);
|
||||
if (!mSectionHeaders)
|
||||
if(!mSectionHeaders)
|
||||
return ErrorSectionHeadersRead;
|
||||
|
||||
//parse the sections
|
||||
auto sectionsError = parseSections(numberOfSections);
|
||||
if (sectionsError != ErrorOk)
|
||||
if(sectionsError != ErrorOk)
|
||||
return sectionsError;
|
||||
|
||||
//TODO: parse data directories
|
||||
|
|
@ -179,13 +179,13 @@ namespace GleeBug
|
|||
|
||||
uint32 Pe::ConvertOffsetToRva(uint32 offset)
|
||||
{
|
||||
if (!mOffsetSectionMap.size()) //TODO: verify this (no sections means direct mapping)
|
||||
if(!mOffsetSectionMap.size()) //TODO: verify this (no sections means direct mapping)
|
||||
return offset;
|
||||
const auto found = mOffsetSectionMap.find(Range(offset, offset));
|
||||
if (found == mOffsetSectionMap.end())
|
||||
if(found == mOffsetSectionMap.end())
|
||||
return INVALID_VALUE;
|
||||
auto index = found->second;
|
||||
if (index == HeaderSection)
|
||||
if(index == HeaderSection)
|
||||
return offset;
|
||||
const auto & section = mSections[index];
|
||||
offset -= uint32(found->first.first); //adjust the offset to be relative to the offset range in the map
|
||||
|
|
@ -194,13 +194,13 @@ namespace GleeBug
|
|||
|
||||
uint32 Pe::ConvertRvaToOffset(uint32 rva)
|
||||
{
|
||||
if (!mRvaSectionMap.size()) //TODO: verify this (no sections means direct mapping)
|
||||
if(!mRvaSectionMap.size()) //TODO: verify this (no sections means direct mapping)
|
||||
return rva;
|
||||
const auto found = mRvaSectionMap.find(Range(rva, rva));
|
||||
if (found == mRvaSectionMap.end())
|
||||
if(found == mRvaSectionMap.end())
|
||||
return INVALID_VALUE;
|
||||
auto index = found->second;
|
||||
if (index == HeaderSection)
|
||||
if(index == HeaderSection)
|
||||
return rva;
|
||||
const auto & section = mSections[index];
|
||||
rva -= uint32(found->first.first); //adjust the rva to be relative to the rva range in the map
|
||||
|
|
@ -209,7 +209,7 @@ namespace GleeBug
|
|||
|
||||
Pe::Error Pe::parseSections(uint16 count, uint32 alignment)
|
||||
{
|
||||
if (!count)
|
||||
if(!count)
|
||||
return ErrorOk;
|
||||
|
||||
auto sectionHeaders = GetSectionHeaders();
|
||||
|
|
@ -225,7 +225,7 @@ namespace GleeBug
|
|||
//sort sections on raw address to prevent read errors and have a contiguous buffer
|
||||
std::vector<SectionInfo> sortedHeaders;
|
||||
sortedHeaders.reserve(count);
|
||||
for (uint16 i = 0; i < count; i++)
|
||||
for(uint16 i = 0; i < count; i++)
|
||||
sortedHeaders.push_back(SectionInfo{ i, sectionHeaders[i] });
|
||||
|
||||
std::sort(sortedHeaders.begin(), sortedHeaders.end(), [](const SectionInfo & a, const SectionInfo & b)
|
||||
|
|
@ -270,14 +270,14 @@ namespace GleeBug
|
|||
|
||||
//add the sections to the mSections vector
|
||||
mSections.reserve(count);
|
||||
for (uint16 i = 0; i < count; i++)
|
||||
for(uint16 i = 0; i < count; i++)
|
||||
{
|
||||
const auto & section = sortedHeaders[i];
|
||||
mSections.push_back(Section(i, alignment, mSectionHeaders, section.beforeData, section.data));
|
||||
}
|
||||
|
||||
//create rva/offset -> section maps
|
||||
if (count) //insert pe header offset/rva (file start -> first section is the PE header)
|
||||
if(count) //insert pe header offset/rva (file start -> first section is the PE header)
|
||||
{
|
||||
const auto & section = mSections[0];
|
||||
mOffsetSectionMap.insert({ Range(0, section.GetHeader().PointerToRawData - 1), HeaderSection });
|
||||
|
|
@ -287,7 +287,7 @@ namespace GleeBug
|
|||
else //TODO: handle file without sections
|
||||
{
|
||||
}
|
||||
for (const auto & section : mSections)
|
||||
for(const auto & section : mSections)
|
||||
{
|
||||
//offset -> section index
|
||||
auto offset = section.GetHeader().PointerToRawData;
|
||||
|
|
@ -308,11 +308,11 @@ namespace GleeBug
|
|||
|
||||
uint32 Pe::readData(uint32 size)
|
||||
{
|
||||
if (!size)
|
||||
if(!size)
|
||||
return mOffset;
|
||||
std::vector<uint8> temp(size);
|
||||
|
||||
if (!mFile.Read(mOffset, temp.data(), size))
|
||||
if(!mFile.Read(mOffset, temp.data(), size))
|
||||
return INVALID_VALUE;
|
||||
|
||||
auto result = mOffset;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace GleeBug
|
|||
*/
|
||||
T* Data() const
|
||||
{
|
||||
if (!Valid())
|
||||
if(!Valid())
|
||||
return nullptr;
|
||||
return (T*)(mData->data() + mOffset);
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ namespace GleeBug
|
|||
/**
|
||||
\brief Returns Data().
|
||||
*/
|
||||
T* operator ()() const
|
||||
T* operator()() const
|
||||
{
|
||||
return Data();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ protected:
|
|||
|
||||
mProcess->MemReadUnsafe(registers.Gip(), dataToExec, 4);
|
||||
printf("\n What are my bytes? I am so lost.. Dump: ");
|
||||
for (int i = 0; i < 4; i++)
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
printf("%02X ", dataToExec[i]);
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ protected:
|
|||
memcpy(dataToExec, tmp, 4);
|
||||
mProcess->MemReadUnsafe(registers.Gip(), dataToExec, 4);
|
||||
printf("\n What are my bytes? I am so lost.. Dump: ");
|
||||
for (int i = 0; i < 4; i++)
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
printf("%02X ", dataToExec[i]);
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ protected:
|
|||
memcpy(dataToExec, tmp, 4);
|
||||
mProcess->MemReadUnsafe(registers.Gip(), dataToExec, 4);
|
||||
printf("\n What are my bytes? I am so lost.. Dump: ");
|
||||
for (int i = 0; i < 4; i++)
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
printf("%02X ", dataToExec[i]);
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ protected:
|
|||
auto addr = registers.Esi();
|
||||
#endif //_WIN64
|
||||
printf("Addr: 0x%p\n", (void*)addr);
|
||||
if (mProcess->SetMemoryBreakpoint(addr, 0x10000, this, &MyDebugger::cbMemoryBreakpoint, MemoryType::Execute, false))
|
||||
if(mProcess->SetMemoryBreakpoint(addr, 0x10000, this, &MyDebugger::cbMemoryBreakpoint, MemoryType::Execute, false))
|
||||
puts("Memory breakpoint set!");
|
||||
else
|
||||
puts("Failed to set memory breakpoint...");
|
||||
|
|
@ -83,7 +83,7 @@ protected:
|
|||
Registers registers(mThread->hThread);
|
||||
printf("Reached entry hardware breakpoint! GIP: 0x%p\n",
|
||||
(void*)registers.Gip());
|
||||
if (mProcess->DeleteHardwareBreakpoint(info.address))
|
||||
if(mProcess->DeleteHardwareBreakpoint(info.address))
|
||||
printf("Entry hardware breakpoint deleted!\n");
|
||||
else
|
||||
printf("Failed to delete entry hardware breakpoint...\n");
|
||||
|
|
@ -133,12 +133,12 @@ protected:
|
|||
ptr start = entry - 2;
|
||||
printf("unsafe: ");
|
||||
mProcess->MemReadUnsafe(start, test, sizeof(test));
|
||||
for (int i = 0; i < sizeof(test); i++)
|
||||
for(int i = 0; i < sizeof(test); i++)
|
||||
printf("%02X ", test[i]);
|
||||
puts("");
|
||||
mProcess->MemReadSafe(start, test, sizeof(test));
|
||||
printf(" safe: ");
|
||||
for (int i = 0; i < sizeof(test); i++)
|
||||
for(int i = 0; i < sizeof(test); i++)
|
||||
printf("%02X ", test[i]);
|
||||
puts("");
|
||||
}
|
||||
|
|
@ -183,7 +183,7 @@ protected:
|
|||
exceptionType,
|
||||
exceptionInfo.ExceptionRecord.ExceptionCode,
|
||||
exceptionInfo.ExceptionRecord.ExceptionAddress);
|
||||
for (DWORD i = 0; i < exceptionInfo.ExceptionRecord.NumberParameters; i++)
|
||||
for(DWORD i = 0; i < exceptionInfo.ExceptionRecord.NumberParameters; i++)
|
||||
printf(" ExceptionInformation[%d] = 0x%p\n", i, (void*)exceptionInfo.ExceptionRecord.ExceptionInformation[i]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ static void testDebugger()
|
|||
wchar_t szCommandLine[256] = L"";
|
||||
wchar_t szCurrentDir[256] = L"c:\\";
|
||||
MyDebugger dbg;
|
||||
if (dbg.Init(szFilePath, szCommandLine, szCurrentDir))
|
||||
if(dbg.Init(szFilePath, szCommandLine, szCurrentDir))
|
||||
{
|
||||
puts("Debugger::Init success!");
|
||||
dbg.Start();
|
||||
|
|
@ -35,7 +35,7 @@ static void printRegion(const char* str, Region<T> region, bool newline = true)
|
|||
region.Size(),
|
||||
region.Valid() ? "true" : "false",
|
||||
region.Empty() ? "true" : "false");
|
||||
if (newline)
|
||||
if(newline)
|
||||
puts("");
|
||||
}
|
||||
|
||||
|
|
@ -65,19 +65,19 @@ static bool testPeFile(const wchar_t* szFileName, bool dumpData = true)
|
|||
using namespace GleeBug;
|
||||
auto result = false;
|
||||
File diskFile(szFileName, File::ReadOnly);
|
||||
if (diskFile.Open())
|
||||
if(diskFile.Open())
|
||||
{
|
||||
auto diskSize = diskFile.GetSize();
|
||||
std::vector<uint8> diskData(diskSize);
|
||||
if (diskFile.Read(0, diskData.data(), diskSize))
|
||||
if(diskFile.Read(0, diskData.data(), diskSize))
|
||||
{
|
||||
BufferFile file(diskData.data(), diskSize);
|
||||
Pe pe(file);
|
||||
auto parseError = pe.Parse(true);
|
||||
if (parseError == Pe::ErrorOk)
|
||||
if(parseError == Pe::ErrorOk)
|
||||
{
|
||||
result = true;
|
||||
if (!dumpData)
|
||||
if(!dumpData)
|
||||
return result;
|
||||
auto idh = pe.GetDosHeader();
|
||||
printRegion("DOS Header:", idh);
|
||||
|
|
@ -87,7 +87,7 @@ static bool testPeFile(const wchar_t* szFileName, bool dumpData = true)
|
|||
auto afterDosData = pe.GetAfterDosData();
|
||||
printRegion("After DOS Data", afterDosData);
|
||||
|
||||
if (pe.IsPe64())
|
||||
if(pe.IsPe64())
|
||||
printNtHeaders(pe.GetNtHeaders64());
|
||||
else
|
||||
printNtHeaders(pe.GetNtHeaders32());
|
||||
|
|
@ -100,9 +100,9 @@ static bool testPeFile(const wchar_t* szFileName, bool dumpData = true)
|
|||
auto afterSectionHeadersData = pe.GetAfterSectionHeadersData();
|
||||
printRegion("After Section Headers Data", afterSectionHeadersData);
|
||||
auto sections = pe.GetSections();
|
||||
for (const auto & section : sections)
|
||||
for(const auto & section : sections)
|
||||
{
|
||||
if (section.GetIndex())
|
||||
if(section.GetIndex())
|
||||
puts("");
|
||||
printf(" Section %d:\n", section.GetIndex());
|
||||
auto cur = section.GetHeader();
|
||||
|
|
@ -118,13 +118,13 @@ static bool testPeFile(const wchar_t* szFileName, bool dumpData = true)
|
|||
}
|
||||
|
||||
printf("\nOffset -> Section:\n");
|
||||
for (auto range : pe.GetOffsetSectionMap())
|
||||
for(auto range : pe.GetOffsetSectionMap())
|
||||
{
|
||||
printf(" %08llX:%08llX -> %d\n", range.first.first, range.first.second, range.second);
|
||||
}
|
||||
|
||||
printf("\nRva -> Section:\n");
|
||||
for (auto range : pe.GetRvaSectionMap())
|
||||
for(auto range : pe.GetRvaSectionMap())
|
||||
{
|
||||
printf(" %08llX:%08llX -> %d\n", range.first.first, range.first.second, range.second);
|
||||
}
|
||||
|
|
@ -145,11 +145,11 @@ static void testCorkami()
|
|||
#include "PeTests.h"
|
||||
wchar_t szBasePath[MAX_PATH] = L"c:\\!exclude\\pe\\bin\\";
|
||||
int okCount = 0;
|
||||
for (auto i = 0; i < _countof(peTestFiles); i++)
|
||||
for(auto i = 0; i < _countof(peTestFiles); i++)
|
||||
{
|
||||
std::wstring fileName(szBasePath);
|
||||
fileName += peTestFiles[i];
|
||||
if (testPeFile(fileName.c_str(), false))
|
||||
if(testPeFile(fileName.c_str(), false))
|
||||
okCount++;
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -108,7 +108,8 @@ public:
|
|||
dwMainThreadId = te.th32ThreadID;
|
||||
}
|
||||
te.dwSize = sizeof(te);
|
||||
} while(Thread32Next(h, &te));
|
||||
}
|
||||
while(Thread32Next(h, &te));
|
||||
}
|
||||
CloseHandle(h);
|
||||
}
|
||||
|
|
@ -244,11 +245,11 @@ public:
|
|||
if(!lpNumberOfBytesRead)
|
||||
lpNumberOfBytesRead = &s;
|
||||
auto x = !!ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead);
|
||||
if (!x && nSize <= 0x1000)
|
||||
if(!x && nSize <= 0x1000)
|
||||
{
|
||||
NtSuspendProcess(hProcess);
|
||||
DWORD oldProtect = 0;
|
||||
if (VirtualProtectEx(hProcess, lpBaseAddress, 0x1000, PAGE_EXECUTE_READWRITE, &oldProtect))
|
||||
if(VirtualProtectEx(hProcess, lpBaseAddress, 0x1000, PAGE_EXECUTE_READWRITE, &oldProtect))
|
||||
{
|
||||
x = !!ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead);
|
||||
VirtualProtectEx(hProcess, lpBaseAddress, 0x1000, oldProtect, &oldProtect);
|
||||
|
|
@ -275,7 +276,7 @@ public:
|
|||
//Engine
|
||||
bool EngineCheckStructAlignment(DWORD StructureType, ULONG_PTR StructureSize) const
|
||||
{
|
||||
if (StructureType == UE_STRUCT_TITAN_ENGINE_CONTEXT)
|
||||
if(StructureType == UE_STRUCT_TITAN_ENGINE_CONTEXT)
|
||||
return StructureSize == sizeof(TITAN_ENGINE_CONTEXT_t);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -292,7 +293,7 @@ public:
|
|||
|
||||
void SetCustomHandler(DWORD ExceptionId, PVOID CallBack)
|
||||
{
|
||||
switch (ExceptionId)
|
||||
switch(ExceptionId)
|
||||
{
|
||||
case UE_CH_CREATEPROCESS:
|
||||
mCbCREATEPROCESS = CUSTOMHANDLER(CallBack);
|
||||
|
|
@ -386,11 +387,11 @@ public:
|
|||
|
||||
HANDLE TitanOpenProcess(DWORD dwDesiredAccess, bool bInheritHandle, DWORD dwProcessId)
|
||||
{
|
||||
if (mSetDebugPrivilege)
|
||||
if(mSetDebugPrivilege)
|
||||
setDebugPrivilege(GetCurrentProcess(), true);
|
||||
HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
|
||||
DWORD dwLastError = GetLastError();
|
||||
if (mSetDebugPrivilege)
|
||||
if(mSetDebugPrivilege)
|
||||
setDebugPrivilege(GetCurrentProcess(), false);
|
||||
SetLastError(dwLastError);
|
||||
return hProcess;
|
||||
|
|
@ -398,11 +399,11 @@ public:
|
|||
|
||||
HANDLE TitanOpenThread(DWORD dwDesiredAccess, bool bInheritHandle, DWORD dwThreadId)
|
||||
{
|
||||
if (mSetDebugPrivilege)
|
||||
if(mSetDebugPrivilege)
|
||||
setDebugPrivilege(GetCurrentProcess(), true);
|
||||
HANDLE hThread = OpenThread(dwDesiredAccess, bInheritHandle, dwThreadId);
|
||||
DWORD dwLastError = GetLastError();
|
||||
if (mSetDebugPrivilege)
|
||||
if(mSetDebugPrivilege)
|
||||
setDebugPrivilege(GetCurrentProcess(), false);
|
||||
SetLastError(dwLastError);
|
||||
return hThread;
|
||||
|
|
@ -476,7 +477,7 @@ public:
|
|||
bool StaticFileLoadW(const wchar_t* szFileName, DWORD DesiredAccess, bool SimulateLoad, LPHANDLE FileHandle, LPDWORD LoadedSize, LPHANDLE FileMap, PULONG_PTR FileMapVA)
|
||||
{
|
||||
auto file = new ::FileMap<unsigned char>;
|
||||
if (!file->Map(szFileName, DesiredAccess == UE_ACCESS_ALL))
|
||||
if(!file->Map(szFileName, DesiredAccess == UE_ACCESS_ALL))
|
||||
__debugbreak(); //return false;
|
||||
*FileHandle = file->hFile;
|
||||
*LoadedSize = file->size;
|
||||
|
|
@ -486,7 +487,7 @@ public:
|
|||
mappedPe.file = std::move(file);
|
||||
mappedPe.buffer = new BufferFile(mappedPe.file->data, mappedPe.file->size);
|
||||
mappedPe.pe = new Pe(*mappedPe.buffer);
|
||||
if (mappedPe.pe->Parse(true) != Pe::ErrorOk)
|
||||
if(mappedPe.pe->Parse(true) != Pe::ErrorOk)
|
||||
__debugbreak();
|
||||
mappedFiles.insert({ *FileMapVA, mappedPe });
|
||||
return true;
|
||||
|
|
@ -495,7 +496,7 @@ public:
|
|||
bool StaticFileUnloadW(const wchar_t* szFileName, bool CommitChanges, HANDLE FileHandle, DWORD LoadedSize, HANDLE FileMap, ULONG_PTR FileMapVA)
|
||||
{
|
||||
auto found = mappedFiles.find(FileMapVA);
|
||||
if (found == mappedFiles.end())
|
||||
if(found == mappedFiles.end())
|
||||
__debugbreak(); //return false;
|
||||
delete found->second.pe;
|
||||
delete found->second.buffer;
|
||||
|
|
@ -517,21 +518,21 @@ public:
|
|||
)
|
||||
{
|
||||
auto found = mappedFiles.find(FileMapVA);
|
||||
if (found == mappedFiles.end())
|
||||
if(found == mappedFiles.end())
|
||||
__debugbreak(); //return 0;
|
||||
|
||||
if (!found->second.pe->IsValidPe())
|
||||
if(!found->second.pe->IsValidPe())
|
||||
__debugbreak(); //return 0;
|
||||
|
||||
if (AddressToConvert < FileMapVA)
|
||||
if(AddressToConvert < FileMapVA)
|
||||
__debugbreak();
|
||||
|
||||
// convert: FileOffset -> VA
|
||||
auto offset = found->second.pe->ConvertOffsetToRva(
|
||||
uint32( AddressToConvert - FileMapVA )
|
||||
uint32(AddressToConvert - FileMapVA)
|
||||
);
|
||||
|
||||
if (offset == INVALID_VALUE)
|
||||
if(offset == INVALID_VALUE)
|
||||
return 0;
|
||||
else
|
||||
return ReturnType ? FileMapVA + offset : offset;
|
||||
|
|
@ -551,8 +552,8 @@ public:
|
|||
)
|
||||
{
|
||||
return ConvertVAtoFileOffsetEx(
|
||||
FileMapVA ,0 ,0 ,
|
||||
AddressToConvert, false, ReturnType );
|
||||
FileMapVA, 0, 0,
|
||||
AddressToConvert, false, ReturnType);
|
||||
}
|
||||
|
||||
////
|
||||
|
|
@ -572,10 +573,10 @@ public:
|
|||
)
|
||||
{
|
||||
auto found = mappedFiles.find(FileMapVA);
|
||||
if (found == mappedFiles.end())
|
||||
if(found == mappedFiles.end())
|
||||
__debugbreak(); //return 0;
|
||||
|
||||
if (!found->second.pe->IsValidPe())
|
||||
if(!found->second.pe->IsValidPe())
|
||||
__debugbreak(); //return 0;
|
||||
|
||||
// Convert to RVA if needed
|
||||
|
|
@ -585,10 +586,10 @@ public:
|
|||
|
||||
// convert: VA -> FileOffset
|
||||
auto offset = found->second.pe->ConvertRvaToOffset(
|
||||
uint32( RVA_ToConvert )
|
||||
uint32(RVA_ToConvert)
|
||||
);
|
||||
|
||||
if (offset == INVALID_VALUE)
|
||||
if(offset == INVALID_VALUE)
|
||||
return 0;
|
||||
else
|
||||
return ReturnType ? FileMapVA + offset : offset;
|
||||
|
|
@ -597,7 +598,7 @@ public:
|
|||
template<typename T>
|
||||
ULONG_PTR GetPE32DataW_impl(const Region<T> & headers, DWORD WhichSection, DWORD WhichData, const std::vector<Section> & sections)
|
||||
{
|
||||
switch (WhichData)
|
||||
switch(WhichData)
|
||||
{
|
||||
case UE_PE_OFFSET:
|
||||
return headers.Offset();
|
||||
|
|
@ -652,9 +653,9 @@ public:
|
|||
ULONG_PTR GetPE32DataFromMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData)
|
||||
{
|
||||
auto found = mappedFiles.find(FileMapVA);
|
||||
if (found == mappedFiles.end())
|
||||
if(found == mappedFiles.end())
|
||||
__debugbreak(); //return 0;
|
||||
if (!found->second.pe->IsValidPe())
|
||||
if(!found->second.pe->IsValidPe())
|
||||
__debugbreak(); //return 0;
|
||||
auto sections = found->second.pe->GetSections();
|
||||
return found->second.pe->IsPe64()
|
||||
|
|
@ -670,13 +671,13 @@ public:
|
|||
ULONG_PTR GetPE32DataW(const wchar_t* szFileName, DWORD WhichSection, DWORD WhichData)
|
||||
{
|
||||
FileMap<unsigned char> file;
|
||||
if (!file.Map(szFileName))
|
||||
if(!file.Map(szFileName))
|
||||
__debugbreak(); //return 0;
|
||||
BufferFile buf(file.data, file.size);
|
||||
Pe pe(buf);
|
||||
if (pe.Parse(true) != Pe::ErrorOk)
|
||||
if(pe.Parse(true) != Pe::ErrorOk)
|
||||
__debugbreak(); //return 0;
|
||||
if (!pe.IsValidPe())
|
||||
if(!pe.IsValidPe())
|
||||
__debugbreak(); //return 0;
|
||||
auto sections = pe.GetSections();
|
||||
return pe.IsPe64()
|
||||
|
|
@ -767,17 +768,17 @@ private: //functions
|
|||
{
|
||||
DWORD dwLastError;
|
||||
HANDLE hToken = 0;
|
||||
if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
||||
if(!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
||||
{
|
||||
dwLastError = GetLastError();
|
||||
if (hToken)
|
||||
if(hToken)
|
||||
CloseHandle(hToken);
|
||||
return dwLastError;
|
||||
}
|
||||
TOKEN_PRIVILEGES tokenPrivileges;
|
||||
memset(&tokenPrivileges, 0, sizeof(TOKEN_PRIVILEGES));
|
||||
LUID luid;
|
||||
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
|
||||
if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
|
||||
{
|
||||
dwLastError = GetLastError();
|
||||
CloseHandle(hToken);
|
||||
|
|
@ -785,7 +786,7 @@ private: //functions
|
|||
}
|
||||
tokenPrivileges.PrivilegeCount = 1;
|
||||
tokenPrivileges.Privileges[0].Luid = luid;
|
||||
if (bEnablePrivilege)
|
||||
if(bEnablePrivilege)
|
||||
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
else
|
||||
tokenPrivileges.Privileges[0].Attributes = 0;
|
||||
|
|
|
|||
|
|
@ -122,10 +122,10 @@ __declspec(dllexport) ULONG_PTR TITCALL ImporterGetRemoteAPIAddressEx(const char
|
|||
static auto hModule = GetModuleHandleW(X64DBG_DLL);
|
||||
#undef X64DBG_DLL
|
||||
|
||||
if (hModule)
|
||||
if(hModule)
|
||||
{
|
||||
static auto DbgValFromString = (ULONG_PTR(*)(const char*))GetProcAddress(hModule, "DbgValFromString");
|
||||
if (DbgValFromString)
|
||||
if(DbgValFromString)
|
||||
{
|
||||
char expr[1024] = "";
|
||||
_snprintf_s(expr, _TRUNCATE, "\"%s\":%s", szDLLName, szAPIName);
|
||||
|
|
@ -293,7 +293,7 @@ BOOL WINAPI DllMain(
|
|||
_In_ LPVOID lpvReserved
|
||||
)
|
||||
{
|
||||
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||
if(fdwReason == DLL_PROCESS_ATTACH)
|
||||
emu.engineHandle = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ public:
|
|||
PROCESS_INFORMATION* InitDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder)
|
||||
{
|
||||
mCbATTACHBREAKPOINT = nullptr;
|
||||
if (!Init(szFileName, szCommandLine, szCurrentFolder))
|
||||
if(!Init(szFileName, szCommandLine, szCurrentFolder))
|
||||
return nullptr;
|
||||
return &mMainProcess;
|
||||
}
|
||||
|
|
@ -36,20 +36,20 @@ public:
|
|||
PROCESS_INFORMATION* InitDLLDebugW(const wchar_t* szFileName, bool /* ReserveModuleBase = false */, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder, LPVOID /*EntryCallBack = 0 */)
|
||||
{
|
||||
wcscpy_s(szDebuggeeName, szFileName);
|
||||
if (TryExtractDllLoader())
|
||||
if(TryExtractDllLoader())
|
||||
{
|
||||
mCbATTACHBREAKPOINT = nullptr;
|
||||
if (!Init(szDebuggeeName, szCommandLine, szCurrentFolder, true, true))
|
||||
if(!Init(szDebuggeeName, szCommandLine, szCurrentFolder, true, true))
|
||||
return nullptr;
|
||||
wchar_t szName[256] = L"";
|
||||
swprintf(szName, 256, L"Local\\szLibraryName%X", mMainProcess.dwProcessId);
|
||||
//TODO: close this once we actually see the DLL is loaded in the process
|
||||
HANDLE DebugDLLFileMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 512 * sizeof(wchar_t), szName);
|
||||
if (DebugDLLFileMapping)
|
||||
if(DebugDLLFileMapping)
|
||||
{
|
||||
const size_t filemapSize = 512;
|
||||
wchar_t* szLibraryPathMapping = (wchar_t*)MapViewOfFile(DebugDLLFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, filemapSize * sizeof(wchar_t));
|
||||
if (szLibraryPathMapping)
|
||||
if(szLibraryPathMapping)
|
||||
{
|
||||
wcscpy_s(szLibraryPathMapping, filemapSize, szFileName);
|
||||
UnmapViewOfFile(szLibraryPathMapping);
|
||||
|
|
@ -98,7 +98,7 @@ public:
|
|||
bool MemoryReadSafe(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead)
|
||||
{
|
||||
auto process = processFromHandle(hProcess);
|
||||
if (!process)
|
||||
if(!process)
|
||||
return false;
|
||||
return process->MemReadSafe(ptr(lpBaseAddress), lpBuffer, nSize, (ptr*)lpNumberOfBytesRead);
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ public:
|
|||
bool MemoryWriteSafe(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten)
|
||||
{
|
||||
auto process = processFromHandle(hProcess);
|
||||
if (!process)
|
||||
if(!process)
|
||||
return false;
|
||||
return process->MemWriteSafe(ptr(lpBaseAddress), lpBuffer, nSize, (ptr*)lpNumberOfBytesWritten);
|
||||
}
|
||||
|
|
@ -114,11 +114,11 @@ public:
|
|||
bool Fill(LPVOID MemoryStart, DWORD MemorySize, PBYTE FillByte)
|
||||
{
|
||||
//TODO: this is fucking inefficient
|
||||
if (!mProcess)
|
||||
if(!mProcess)
|
||||
return false;
|
||||
for (DWORD i = 0; i < MemorySize; i++)
|
||||
for(DWORD i = 0; i < MemorySize; i++)
|
||||
{
|
||||
if (!mProcess->MemWriteSafe(ptr(MemoryStart) + i, FillByte, 1))
|
||||
if(!mProcess->MemWriteSafe(ptr(MemoryStart) + i, FillByte, 1))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -127,7 +127,7 @@ public:
|
|||
//Engine
|
||||
bool EngineCheckStructAlignment(DWORD StructureType, ULONG_PTR StructureSize) const
|
||||
{
|
||||
if (StructureType == UE_STRUCT_TITAN_ENGINE_CONTEXT)
|
||||
if(StructureType == UE_STRUCT_TITAN_ENGINE_CONTEXT)
|
||||
return StructureSize == sizeof(TITAN_ENGINE_CONTEXT_t);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -144,7 +144,7 @@ public:
|
|||
|
||||
void SetCustomHandler(DWORD ExceptionId, PVOID CallBack)
|
||||
{
|
||||
switch (ExceptionId)
|
||||
switch(ExceptionId)
|
||||
{
|
||||
case UE_CH_CREATEPROCESS:
|
||||
mCbCREATEPROCESS = CUSTOMHANDLER(CallBack);
|
||||
|
|
@ -183,7 +183,7 @@ public:
|
|||
|
||||
void SetEngineVariable(DWORD VariableId, bool VariableSet)
|
||||
{
|
||||
switch (VariableId)
|
||||
switch(VariableId)
|
||||
{
|
||||
case UE_ENGINE_SET_DEBUG_PRIVILEGE:
|
||||
mSetDebugPrivilege = VariableSet;
|
||||
|
|
@ -303,7 +303,7 @@ public:
|
|||
ULONG_PTR GetDebuggedFileBaseAddress()
|
||||
{
|
||||
auto itr = mProcesses.find(mMainProcess.dwProcessId);
|
||||
if (itr != mProcesses.end())
|
||||
if(itr != mProcesses.end())
|
||||
return (ULONG_PTR)itr->second->createProcessInfo.lpBaseOfImage;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -311,14 +311,14 @@ public:
|
|||
//Stepping
|
||||
void StepOver(LPVOID CallBack)
|
||||
{
|
||||
if (!mProcess || !CallBack)
|
||||
if(!mProcess || !CallBack)
|
||||
return;
|
||||
mProcess->StepOver(STEPCALLBACK(CallBack));
|
||||
}
|
||||
|
||||
void StepInto(LPVOID CallBack)
|
||||
{
|
||||
if (!mThread || !CallBack)
|
||||
if(!mThread || !CallBack)
|
||||
return;
|
||||
mThread->StepInto(STEPCALLBACK(CallBack));
|
||||
}
|
||||
|
|
@ -328,7 +328,7 @@ public:
|
|||
ThreadSuspender(HANDLE hThread, bool running)
|
||||
: hThread(running ? hThread : nullptr)
|
||||
{
|
||||
if (this->hThread)
|
||||
if(this->hThread)
|
||||
SuspendThread(this->hThread);
|
||||
}
|
||||
|
||||
|
|
@ -337,7 +337,7 @@ public:
|
|||
|
||||
~ThreadSuspender()
|
||||
{
|
||||
if (this->hThread)
|
||||
if(this->hThread)
|
||||
ResumeThread(this->hThread);
|
||||
}
|
||||
|
||||
|
|
@ -347,36 +347,36 @@ public:
|
|||
//Registers
|
||||
ULONG_PTR GetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister)
|
||||
{
|
||||
if (!hActiveThread)
|
||||
if(!hActiveThread)
|
||||
return 0;
|
||||
|
||||
ThreadSuspender suspender(hActiveThread, mIsRunning);
|
||||
auto r = registerFromDword(IndexOfRegister);
|
||||
if (r == Registers::R::Invalid)
|
||||
if(r == Registers::R::Invalid)
|
||||
__debugbreak();
|
||||
return Registers(hActiveThread).Get(r);
|
||||
}
|
||||
|
||||
bool SetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister, ULONG_PTR NewRegisterValue)
|
||||
{
|
||||
if (!hActiveThread)
|
||||
if(!hActiveThread)
|
||||
return 0;
|
||||
|
||||
ThreadSuspender suspender(hActiveThread, mIsRunning);
|
||||
|
||||
auto r = registerFromDword(IndexOfRegister);
|
||||
if (r != Registers::R::Invalid)
|
||||
if(r != Registers::R::Invalid)
|
||||
{
|
||||
Registers(hActiveThread).Set(r, NewRegisterValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
TITAN_ENGINE_CONTEXT_t titcontext;
|
||||
if (!_GetFullContextDataEx(hActiveThread, &titcontext, IndexOfRegister >= UE_MXCSR))
|
||||
if(!_GetFullContextDataEx(hActiveThread, &titcontext, IndexOfRegister >= UE_MXCSR))
|
||||
return false;
|
||||
|
||||
bool avx_priority = false;
|
||||
switch (IndexOfRegister)
|
||||
switch(IndexOfRegister)
|
||||
{
|
||||
case UE_X87_STATUSWORD:
|
||||
{
|
||||
|
|
@ -481,7 +481,8 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
default: __debugbreak();
|
||||
default:
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
return _SetFullContextDataEx(hActiveThread, &titcontext, avx_priority);
|
||||
|
|
@ -505,7 +506,7 @@ public:
|
|||
DWORD x87r0_position = Getx87r0PositionInRegisterArea(STInTopStack);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
for(i = 0; i < 8; i++)
|
||||
mmx[i] = *((uint64_t*)GetRegisterAreaOf87register(titcontext->RegisterArea, x87r0_position, i));
|
||||
}
|
||||
|
||||
|
|
@ -522,7 +523,7 @@ public:
|
|||
int STInTopStack = GetSTInTOPStackFromStatusWord(titcontext->x87fpu.StatusWord);
|
||||
DWORD x87r0_position = Getx87r0PositionInRegisterArea(STInTopStack);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
memcpy(x87FPURegisters[i].data, GetRegisterAreaOf87register(titcontext->RegisterArea, x87r0_position, i), 10);
|
||||
x87FPURegisters[i].st_value = GetSTValueFromIndex(x87r0_position, i);
|
||||
|
|
@ -595,15 +596,15 @@ public:
|
|||
if(!found->second.pe->IsValidPe())
|
||||
__debugbreak(); //return 0;
|
||||
|
||||
if (AddressToConvert < FileMapVA)
|
||||
if(AddressToConvert < FileMapVA)
|
||||
__debugbreak();
|
||||
|
||||
// convert: FileOffset -> VA
|
||||
auto offset = found->second.pe->ConvertOffsetToRva(
|
||||
uint32( AddressToConvert - FileMapVA )
|
||||
uint32(AddressToConvert - FileMapVA)
|
||||
);
|
||||
|
||||
if (offset == INVALID_VALUE)
|
||||
if(offset == INVALID_VALUE)
|
||||
return 0;
|
||||
else
|
||||
return ReturnType ? FileMapVA + offset : offset;
|
||||
|
|
@ -623,8 +624,8 @@ public:
|
|||
)
|
||||
{
|
||||
return ConvertVAtoFileOffsetEx(
|
||||
FileMapVA ,0 ,0 ,
|
||||
AddressToConvert, false, ReturnType );
|
||||
FileMapVA, 0, 0,
|
||||
AddressToConvert, false, ReturnType);
|
||||
}
|
||||
|
||||
////
|
||||
|
|
@ -657,10 +658,10 @@ public:
|
|||
|
||||
// convert: VA -> FileOffset
|
||||
auto offset = found->second.pe->ConvertRvaToOffset(
|
||||
uint32( RVA_ToConvert )
|
||||
uint32(RVA_ToConvert)
|
||||
);
|
||||
|
||||
if (offset == INVALID_VALUE)
|
||||
if(offset == INVALID_VALUE)
|
||||
return 0;
|
||||
else
|
||||
return ReturnType ? FileMapVA + offset : offset;
|
||||
|
|
@ -764,7 +765,7 @@ public:
|
|||
//Software Breakpoints
|
||||
bool SetBPX(ULONG_PTR bpxAddress, DWORD bpxType, LPVOID bpxCallBack)
|
||||
{
|
||||
if (!mProcess)
|
||||
if(!mProcess)
|
||||
return false;
|
||||
return mProcess->SetBreakpoint(bpxAddress, [bpxCallBack](const BreakpointInfo &)
|
||||
{
|
||||
|
|
@ -774,7 +775,7 @@ public:
|
|||
|
||||
bool DeleteBPX(ULONG_PTR bpxAddress)
|
||||
{
|
||||
if (!mProcess)
|
||||
if(!mProcess)
|
||||
return false;
|
||||
return mProcess->DeleteBreakpoint(bpxAddress);
|
||||
}
|
||||
|
|
@ -792,7 +793,7 @@ public:
|
|||
//Memory Breakpoints
|
||||
bool SetMemoryBPXEx(ULONG_PTR MemoryStart, SIZE_T SizeOfMemory, DWORD BreakPointType, bool RestoreOnHit, LPVOID bpxCallBack)
|
||||
{
|
||||
if (!mProcess)
|
||||
if(!mProcess)
|
||||
return false;
|
||||
return mProcess->SetMemoryBreakpoint(ptr(MemoryStart), ptr(SizeOfMemory), [bpxCallBack](const BreakpointInfo & info)
|
||||
{
|
||||
|
|
@ -802,7 +803,7 @@ public:
|
|||
|
||||
bool RemoveMemoryBPX(ULONG_PTR MemoryStart, SIZE_T SizeOfMemory)
|
||||
{
|
||||
if (!mProcess)
|
||||
if(!mProcess)
|
||||
return false;
|
||||
return mProcess->DeleteMemoryBreakpoint(ptr(MemoryStart));
|
||||
}
|
||||
|
|
@ -810,7 +811,7 @@ public:
|
|||
//Hardware Breakpoints
|
||||
bool SetHardwareBreakPoint(ULONG_PTR bpxAddress, DWORD IndexOfRegister, DWORD bpxType, DWORD bpxSize, LPVOID bpxCallBack)
|
||||
{
|
||||
if (!mProcess)
|
||||
if(!mProcess)
|
||||
return false;
|
||||
auto running = mIsRunning;
|
||||
if(running)
|
||||
|
|
@ -834,7 +835,7 @@ public:
|
|||
|
||||
bool DeleteHardwareBreakPoint(DWORD IndexOfRegister)
|
||||
{
|
||||
if (!mProcess || IndexOfRegister > 3)
|
||||
if(!mProcess || IndexOfRegister > 3)
|
||||
return false;
|
||||
auto address = mProcess->hardwareBreakpoints[IndexOfRegister].address;
|
||||
return mProcess->DeleteHardwareBreakpoint(address);
|
||||
|
|
@ -842,11 +843,11 @@ public:
|
|||
|
||||
bool GetUnusedHardwareBreakPointRegister(LPDWORD RegisterIndex)
|
||||
{
|
||||
if (!mProcess || !RegisterIndex)
|
||||
if(!mProcess || !RegisterIndex)
|
||||
return false;
|
||||
HardwareSlot slot;
|
||||
bool result = mProcess->GetFreeHardwareBreakpointSlot(slot);
|
||||
if (result)
|
||||
if(result)
|
||||
*RegisterIndex = (DWORD)slot;
|
||||
return result;
|
||||
}
|
||||
|
|
@ -866,55 +867,55 @@ public:
|
|||
protected:
|
||||
void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const Process & process) override
|
||||
{
|
||||
if (mCbCREATEPROCESS)
|
||||
if(mCbCREATEPROCESS)
|
||||
mCbCREATEPROCESS(&createProcess);
|
||||
}
|
||||
|
||||
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const Process & process) override
|
||||
{
|
||||
if (mCbEXITPROCESS)
|
||||
if(mCbEXITPROCESS)
|
||||
mCbEXITPROCESS(&exitProcess);
|
||||
}
|
||||
|
||||
void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const Thread & thread) override
|
||||
{
|
||||
if (mCbCREATETHREAD)
|
||||
if(mCbCREATETHREAD)
|
||||
mCbCREATETHREAD(&createThread);
|
||||
}
|
||||
|
||||
void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const Thread & thread) override
|
||||
{
|
||||
if (mCbEXITTHREAD)
|
||||
if(mCbEXITTHREAD)
|
||||
mCbEXITTHREAD(&exitThread);
|
||||
}
|
||||
|
||||
void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) override
|
||||
{
|
||||
if (mCbLOADDLL)
|
||||
if(mCbLOADDLL)
|
||||
mCbLOADDLL(&loadDll);
|
||||
}
|
||||
|
||||
void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll) override
|
||||
{
|
||||
if (mCbUNLOADDLL)
|
||||
if(mCbUNLOADDLL)
|
||||
mCbUNLOADDLL(&unloadDll);
|
||||
}
|
||||
|
||||
void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) override
|
||||
{
|
||||
if (mCbUNHANDLEDEXCEPTION)
|
||||
if(mCbUNHANDLEDEXCEPTION)
|
||||
mCbUNHANDLEDEXCEPTION(&mDebugEvent.u.Exception);
|
||||
}
|
||||
|
||||
void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) override
|
||||
{
|
||||
if (mCbOUTPUTDEBUGSTRING)
|
||||
if(mCbOUTPUTDEBUGSTRING)
|
||||
mCbOUTPUTDEBUGSTRING(&debugString);
|
||||
}
|
||||
|
||||
void cbPreDebugEvent(const DEBUG_EVENT & debugEvent) override
|
||||
{
|
||||
if (mCbDEBUGEVENT)
|
||||
if(mCbDEBUGEVENT)
|
||||
mCbDEBUGEVENT(&debugEvent);
|
||||
}
|
||||
|
||||
|
|
@ -930,60 +931,103 @@ protected:
|
|||
|
||||
void cbSystemBreakpoint() override
|
||||
{
|
||||
if (mCbSYSTEMBREAKPOINT)
|
||||
if(mCbSYSTEMBREAKPOINT)
|
||||
mCbSYSTEMBREAKPOINT(&mDebugEvent.u.Exception);
|
||||
}
|
||||
|
||||
private: //functions
|
||||
inline Registers::R registerFromDword(DWORD IndexOfRegister)
|
||||
{
|
||||
switch (IndexOfRegister)
|
||||
switch(IndexOfRegister)
|
||||
{
|
||||
case UE_EAX: return Registers::R::EAX;
|
||||
case UE_EBX: return Registers::R::EBX;
|
||||
case UE_ECX: return Registers::R::ECX;
|
||||
case UE_EDX: return Registers::R::EDX;
|
||||
case UE_EDI: return Registers::R::EDI;
|
||||
case UE_ESI: return Registers::R::ESI;
|
||||
case UE_EBP: return Registers::R::EBP;
|
||||
case UE_ESP: return Registers::R::ESP;
|
||||
case UE_EIP: return Registers::R::EIP;
|
||||
case UE_EFLAGS: return Registers::R::EFlags;
|
||||
case UE_DR0: return Registers::R::DR0;
|
||||
case UE_DR1: return Registers::R::DR1;
|
||||
case UE_DR2: return Registers::R::DR2;
|
||||
case UE_DR3: return Registers::R::DR3;
|
||||
case UE_DR6: return Registers::R::DR6;
|
||||
case UE_DR7: return Registers::R::DR7;
|
||||
case UE_EAX:
|
||||
return Registers::R::EAX;
|
||||
case UE_EBX:
|
||||
return Registers::R::EBX;
|
||||
case UE_ECX:
|
||||
return Registers::R::ECX;
|
||||
case UE_EDX:
|
||||
return Registers::R::EDX;
|
||||
case UE_EDI:
|
||||
return Registers::R::EDI;
|
||||
case UE_ESI:
|
||||
return Registers::R::ESI;
|
||||
case UE_EBP:
|
||||
return Registers::R::EBP;
|
||||
case UE_ESP:
|
||||
return Registers::R::ESP;
|
||||
case UE_EIP:
|
||||
return Registers::R::EIP;
|
||||
case UE_EFLAGS:
|
||||
return Registers::R::EFlags;
|
||||
case UE_DR0:
|
||||
return Registers::R::DR0;
|
||||
case UE_DR1:
|
||||
return Registers::R::DR1;
|
||||
case UE_DR2:
|
||||
return Registers::R::DR2;
|
||||
case UE_DR3:
|
||||
return Registers::R::DR3;
|
||||
case UE_DR6:
|
||||
return Registers::R::DR6;
|
||||
case UE_DR7:
|
||||
return Registers::R::DR7;
|
||||
#ifdef _WIN64
|
||||
case UE_RAX: return Registers::R::RAX;
|
||||
case UE_RBX: return Registers::R::RBX;
|
||||
case UE_RCX: return Registers::R::RCX;
|
||||
case UE_RDX: return Registers::R::RDX;
|
||||
case UE_RDI: return Registers::R::RDI;
|
||||
case UE_RSI: return Registers::R::RSI;
|
||||
case UE_RBP: return Registers::R::RBP;
|
||||
case UE_RSP: return Registers::R::RSP;
|
||||
case UE_RIP: return Registers::R::RIP;
|
||||
case UE_RFLAGS: return Registers::R::EFlags;
|
||||
case UE_R8: return Registers::R::R8;
|
||||
case UE_R9: return Registers::R::R9;
|
||||
case UE_R10: return Registers::R::R10;
|
||||
case UE_R11: return Registers::R::R11;
|
||||
case UE_R12: return Registers::R::R12;
|
||||
case UE_R13: return Registers::R::R13;
|
||||
case UE_R14: return Registers::R::R14;
|
||||
case UE_R15: return Registers::R::R15;
|
||||
case UE_RAX:
|
||||
return Registers::R::RAX;
|
||||
case UE_RBX:
|
||||
return Registers::R::RBX;
|
||||
case UE_RCX:
|
||||
return Registers::R::RCX;
|
||||
case UE_RDX:
|
||||
return Registers::R::RDX;
|
||||
case UE_RDI:
|
||||
return Registers::R::RDI;
|
||||
case UE_RSI:
|
||||
return Registers::R::RSI;
|
||||
case UE_RBP:
|
||||
return Registers::R::RBP;
|
||||
case UE_RSP:
|
||||
return Registers::R::RSP;
|
||||
case UE_RIP:
|
||||
return Registers::R::RIP;
|
||||
case UE_RFLAGS:
|
||||
return Registers::R::EFlags;
|
||||
case UE_R8:
|
||||
return Registers::R::R8;
|
||||
case UE_R9:
|
||||
return Registers::R::R9;
|
||||
case UE_R10:
|
||||
return Registers::R::R10;
|
||||
case UE_R11:
|
||||
return Registers::R::R11;
|
||||
case UE_R12:
|
||||
return Registers::R::R12;
|
||||
case UE_R13:
|
||||
return Registers::R::R13;
|
||||
case UE_R14:
|
||||
return Registers::R::R14;
|
||||
case UE_R15:
|
||||
return Registers::R::R15;
|
||||
#endif //_WIN64
|
||||
case UE_CIP: return Registers::R::GIP;
|
||||
case UE_CSP: return Registers::R::GSP;
|
||||
case UE_SEG_GS: return Registers::R::GS;
|
||||
case UE_SEG_FS: return Registers::R::FS;
|
||||
case UE_SEG_ES: return Registers::R::ES;
|
||||
case UE_SEG_DS: return Registers::R::DS;
|
||||
case UE_SEG_CS: return Registers::R::CS;
|
||||
case UE_SEG_SS: return Registers::R::SS;
|
||||
default: return Registers::R::Invalid;
|
||||
case UE_CIP:
|
||||
return Registers::R::GIP;
|
||||
case UE_CSP:
|
||||
return Registers::R::GSP;
|
||||
case UE_SEG_GS:
|
||||
return Registers::R::GS;
|
||||
case UE_SEG_FS:
|
||||
return Registers::R::FS;
|
||||
case UE_SEG_ES:
|
||||
return Registers::R::ES;
|
||||
case UE_SEG_DS:
|
||||
return Registers::R::DS;
|
||||
case UE_SEG_CS:
|
||||
return Registers::R::CS;
|
||||
case UE_SEG_SS:
|
||||
return Registers::R::SS;
|
||||
default:
|
||||
return Registers::R::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1037,7 +1081,7 @@ private: //functions
|
|||
|
||||
static HardwareType hwtypeFromTitan(DWORD type)
|
||||
{
|
||||
switch (type)
|
||||
switch(type)
|
||||
{
|
||||
case UE_HARDWARE_EXECUTE:
|
||||
return HardwareType::Execute;
|
||||
|
|
@ -1052,7 +1096,7 @@ private: //functions
|
|||
|
||||
static HardwareSize hwsizeFromTitan(DWORD size)
|
||||
{
|
||||
switch (size)
|
||||
switch(size)
|
||||
{
|
||||
case UE_HARDWARE_SIZE_1:
|
||||
return HardwareSize::SizeByte;
|
||||
|
|
@ -1071,7 +1115,7 @@ private: //functions
|
|||
|
||||
static MemoryType memtypeFromTitan(DWORD type)
|
||||
{
|
||||
switch (type)
|
||||
switch(type)
|
||||
{
|
||||
case UE_MEMORY:
|
||||
return MemoryType::Access;
|
||||
|
|
@ -1209,18 +1253,18 @@ private: //functions
|
|||
{
|
||||
bool result = false;
|
||||
HRSRC hResource = FindResourceA(engineHandle, (LPCSTR)szResourceName, "BINARY");
|
||||
if (hResource != NULL)
|
||||
if(hResource != NULL)
|
||||
{
|
||||
HGLOBAL hResourceGlobal = LoadResource(engineHandle, hResource);
|
||||
if (hResourceGlobal != NULL)
|
||||
if(hResourceGlobal != NULL)
|
||||
{
|
||||
DWORD ResourceSize = SizeofResource(engineHandle, hResource);
|
||||
LPVOID ResourceData = LockResource(hResourceGlobal);
|
||||
HANDLE hFile = CreateFileW(szExtractedFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD NumberOfBytesWritten;
|
||||
if (WriteFile(hFile, ResourceData, ResourceSize, &NumberOfBytesWritten, NULL))
|
||||
if(WriteFile(hFile, ResourceData, ResourceSize, &NumberOfBytesWritten, NULL))
|
||||
result = true;
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
|
@ -1232,7 +1276,7 @@ private: //functions
|
|||
bool TryExtractDllLoader(bool failedBefore = false)
|
||||
{
|
||||
wchar_t* szPath = wcsrchr(szDebuggeeName, L'\\');
|
||||
if (szPath)
|
||||
if(szPath)
|
||||
szPath[1] = '\0';
|
||||
wchar_t DLLLoaderName[64] = L"";
|
||||
#ifdef _WIN64
|
||||
|
|
@ -1242,9 +1286,9 @@ private: //functions
|
|||
#endif //_WIN64
|
||||
wcscat_s(szDebuggeeName, DLLLoaderName);
|
||||
#ifdef _WIN64
|
||||
if (EngineExtractResource("LOADERX64", szDebuggeeName))
|
||||
if(EngineExtractResource("LOADERX64", szDebuggeeName))
|
||||
#else
|
||||
if (EngineExtractResource("LOADERX86", szDebuggeeName))
|
||||
if(EngineExtractResource("LOADERX86", szDebuggeeName))
|
||||
#endif //_WIN64
|
||||
return true;
|
||||
return !failedBefore &&
|
||||
|
|
|
|||
|
|
@ -145,11 +145,11 @@ SETXSTATEFEATURESMASK _SetXStateFeaturesMask = NULL;
|
|||
|
||||
static bool SetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext)
|
||||
{
|
||||
if (InitXState() == false)
|
||||
if(InitXState() == false)
|
||||
return false;
|
||||
|
||||
DWORD64 FeatureMask = _GetEnabledXStateFeatures();
|
||||
if ((FeatureMask & XSTATE_MASK_AVX) == 0)
|
||||
if((FeatureMask & XSTATE_MASK_AVX) == 0)
|
||||
return false;
|
||||
|
||||
DWORD ContextSize = 0;
|
||||
|
|
@ -158,13 +158,13 @@ static bool SetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titconte
|
|||
NULL,
|
||||
&ContextSize);
|
||||
|
||||
if ((Success == TRUE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
|
||||
if((Success == TRUE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
|
||||
return false;
|
||||
|
||||
std::vector<unsigned char> dataBuffer;
|
||||
dataBuffer.resize(ContextSize);
|
||||
PVOID Buffer = dataBuffer.data();
|
||||
if (Buffer == NULL)
|
||||
if(Buffer == NULL)
|
||||
return false;
|
||||
|
||||
PCONTEXT Context;
|
||||
|
|
@ -172,16 +172,16 @@ static bool SetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titconte
|
|||
CONTEXT_ALL | CONTEXT_XSTATE,
|
||||
&Context,
|
||||
&ContextSize);
|
||||
if (Success == FALSE)
|
||||
if(Success == FALSE)
|
||||
return false;
|
||||
|
||||
if (_SetXStateFeaturesMask(Context, XSTATE_MASK_AVX) == FALSE)
|
||||
if(_SetXStateFeaturesMask(Context, XSTATE_MASK_AVX) == FALSE)
|
||||
return false;
|
||||
|
||||
if (GetThreadContext(hActiveThread, Context) == FALSE)
|
||||
if(GetThreadContext(hActiveThread, Context) == FALSE)
|
||||
return false;
|
||||
|
||||
if (_GetXStateFeaturesMask(Context, &FeatureMask) == FALSE)
|
||||
if(_GetXStateFeaturesMask(Context, &FeatureMask) == FALSE)
|
||||
return false;
|
||||
|
||||
DWORD FeatureLength;
|
||||
|
|
@ -189,15 +189,15 @@ static bool SetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titconte
|
|||
XmmRegister_t* Avx = (XmmRegister_t*)_LocateXStateFeature(Context, XSTATE_AVX, NULL);
|
||||
int NumberOfRegisters = FeatureLength / sizeof(Sse[0]);
|
||||
|
||||
if (Sse != NULL) //If the feature is unsupported by the processor it will return NULL
|
||||
if(Sse != NULL) //If the feature is unsupported by the processor it will return NULL
|
||||
{
|
||||
for (int i = 0; i < NumberOfRegisters; i++)
|
||||
for(int i = 0; i < NumberOfRegisters; i++)
|
||||
Sse[i] = titcontext->YmmRegisters[i].Low;
|
||||
}
|
||||
|
||||
if (Avx != NULL) //If the feature is unsupported by the processor it will return NULL
|
||||
if(Avx != NULL) //If the feature is unsupported by the processor it will return NULL
|
||||
{
|
||||
for (int i = 0; i < NumberOfRegisters; i++)
|
||||
for(int i = 0; i < NumberOfRegisters; i++)
|
||||
Avx[i] = titcontext->YmmRegisters[i].High;
|
||||
}
|
||||
|
||||
|
|
@ -206,11 +206,11 @@ static bool SetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titconte
|
|||
|
||||
static bool GetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext)
|
||||
{
|
||||
if (InitXState() == false)
|
||||
if(InitXState() == false)
|
||||
return false;
|
||||
|
||||
DWORD64 FeatureMask = _GetEnabledXStateFeatures();
|
||||
if ((FeatureMask & XSTATE_MASK_AVX) == 0)
|
||||
if((FeatureMask & XSTATE_MASK_AVX) == 0)
|
||||
return false;
|
||||
|
||||
DWORD ContextSize = 0;
|
||||
|
|
@ -219,13 +219,13 @@ static bool GetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titconte
|
|||
NULL,
|
||||
&ContextSize);
|
||||
|
||||
if ((Success == TRUE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
|
||||
if((Success == TRUE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
|
||||
return false;
|
||||
|
||||
std::vector<unsigned char> dataBuffer;
|
||||
dataBuffer.resize(ContextSize);
|
||||
PVOID Buffer = dataBuffer.data();
|
||||
if (Buffer == NULL)
|
||||
if(Buffer == NULL)
|
||||
return false;
|
||||
|
||||
PCONTEXT Context;
|
||||
|
|
@ -233,16 +233,16 @@ static bool GetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titconte
|
|||
CONTEXT_ALL | CONTEXT_XSTATE,
|
||||
&Context,
|
||||
&ContextSize);
|
||||
if (Success == FALSE)
|
||||
if(Success == FALSE)
|
||||
return false;
|
||||
|
||||
if (_SetXStateFeaturesMask(Context, XSTATE_MASK_AVX) == FALSE)
|
||||
if(_SetXStateFeaturesMask(Context, XSTATE_MASK_AVX) == FALSE)
|
||||
return false;
|
||||
|
||||
if (GetThreadContext(hActiveThread, Context) == FALSE)
|
||||
if(GetThreadContext(hActiveThread, Context) == FALSE)
|
||||
return false;
|
||||
|
||||
if (_GetXStateFeaturesMask(Context, &FeatureMask) == FALSE)
|
||||
if(_GetXStateFeaturesMask(Context, &FeatureMask) == FALSE)
|
||||
return false;
|
||||
|
||||
DWORD FeatureLength;
|
||||
|
|
@ -250,15 +250,15 @@ static bool GetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titconte
|
|||
XmmRegister_t* Avx = (XmmRegister_t*)_LocateXStateFeature(Context, XSTATE_AVX, NULL);
|
||||
int NumberOfRegisters = FeatureLength / sizeof(Sse[0]);
|
||||
|
||||
if (Sse != NULL) //If the feature is unsupported by the processor it will return NULL
|
||||
if(Sse != NULL) //If the feature is unsupported by the processor it will return NULL
|
||||
{
|
||||
for (int i = 0; i < NumberOfRegisters; i++)
|
||||
for(int i = 0; i < NumberOfRegisters; i++)
|
||||
titcontext->YmmRegisters[i].Low = Sse[i];
|
||||
}
|
||||
|
||||
if (Avx != NULL) //If the feature is unsupported by the processor it will return NULL
|
||||
if(Avx != NULL) //If the feature is unsupported by the processor it will return NULL
|
||||
{
|
||||
for (int i = 0; i < NumberOfRegisters; i++)
|
||||
for(int i = 0; i < NumberOfRegisters; i++)
|
||||
titcontext->YmmRegisters[i].High = Avx[i];
|
||||
}
|
||||
|
||||
|
|
@ -272,7 +272,7 @@ bool _SetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcont
|
|||
|
||||
DBGContext.ContextFlags = CONTEXT_ALL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
|
||||
|
||||
if (!GetThreadContext(hActiveThread, &DBGContext))
|
||||
if(!GetThreadContext(hActiveThread, &DBGContext))
|
||||
return false;
|
||||
|
||||
DBGContext.EFlags = (DWORD)titcontext->eflags;
|
||||
|
|
@ -356,7 +356,7 @@ bool _SetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcont
|
|||
|
||||
bool returnf = !!SetThreadContext(hActiveThread, &DBGContext);
|
||||
|
||||
if (AVX_PRIORITY)
|
||||
if(AVX_PRIORITY)
|
||||
SetAVXContext(hActiveThread, titcontext);
|
||||
|
||||
return returnf;
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ IsWindowsVistaOrGreater()
|
|||
|
||||
static int getHeapFlagsOffset(bool x64)
|
||||
{
|
||||
if (x64) //x64 offsets
|
||||
if(x64) //x64 offsets
|
||||
{
|
||||
if (IsWindowsVistaOrGreater())
|
||||
if(IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x70;
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ static int getHeapFlagsOffset(bool x64)
|
|||
}
|
||||
else //x86 offsets
|
||||
{
|
||||
if (IsWindowsVistaOrGreater())
|
||||
if(IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x40;
|
||||
}
|
||||
|
|
@ -67,9 +67,9 @@ static int getHeapFlagsOffset(bool x64)
|
|||
|
||||
static int getHeapForceFlagsOffset(bool x64)
|
||||
{
|
||||
if (x64) //x64 offsets
|
||||
if(x64) //x64 offsets
|
||||
{
|
||||
if (IsWindowsVistaOrGreater())
|
||||
if(IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x74;
|
||||
}
|
||||
|
|
@ -80,7 +80,7 @@ static int getHeapForceFlagsOffset(bool x64)
|
|||
}
|
||||
else //x86 offsets
|
||||
{
|
||||
if (IsWindowsVistaOrGreater())
|
||||
if(IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x44;
|
||||
}
|
||||
|
|
@ -97,13 +97,13 @@ static void* GetPEBLocation_(HANDLE hProcess)
|
|||
void* PebAddress = 0;
|
||||
PROCESS_BASIC_INFORMATION myProcessBasicInformation[5] = { 0 };
|
||||
|
||||
if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, sizeof(PROCESS_BASIC_INFORMATION), &RequiredLen) == 0)
|
||||
if(NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, sizeof(PROCESS_BASIC_INFORMATION), &RequiredLen) == 0)
|
||||
{
|
||||
PebAddress = (void*)myProcessBasicInformation->PebBaseAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, RequiredLen, &RequiredLen) == 0)
|
||||
if(NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, RequiredLen, &RequiredLen) == 0)
|
||||
{
|
||||
PebAddress = (void*)myProcessBasicInformation->PebBaseAddress;
|
||||
}
|
||||
|
|
@ -123,20 +123,20 @@ static bool PebPatchHeapFlags(PEB_CURRENT* peb, HANDLE hProcess)
|
|||
std::vector<PVOID> heaps;
|
||||
heaps.resize(peb->NumberOfHeaps);
|
||||
|
||||
if (ReadProcessMemory(hProcess, (PVOID)peb->ProcessHeaps, (PVOID)heaps.data(), heaps.size() * sizeof(PVOID), nullptr) == FALSE)
|
||||
if(ReadProcessMemory(hProcess, (PVOID)peb->ProcessHeaps, (PVOID)heaps.data(), heaps.size() * sizeof(PVOID), nullptr) == FALSE)
|
||||
return false;
|
||||
|
||||
std::basic_string<uint8_t> heap;
|
||||
heap.resize(0x100); // hacky
|
||||
for (DWORD i = 0; i < peb->NumberOfHeaps; i++)
|
||||
for(DWORD i = 0; i < peb->NumberOfHeaps; i++)
|
||||
{
|
||||
if (ReadProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE)
|
||||
if(ReadProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE)
|
||||
return false;
|
||||
|
||||
auto flags = (DWORD *)(heap.data() + getHeapFlagsOffset(is_x64));
|
||||
auto force_flags = (DWORD *)(heap.data() + getHeapForceFlagsOffset(is_x64));
|
||||
auto flags = (DWORD*)(heap.data() + getHeapFlagsOffset(is_x64));
|
||||
auto force_flags = (DWORD*)(heap.data() + getHeapForceFlagsOffset(is_x64));
|
||||
|
||||
if (i == 0)
|
||||
if(i == 0)
|
||||
{
|
||||
// Default heap.
|
||||
*flags &= HEAP_GROWABLE;
|
||||
|
|
@ -149,7 +149,7 @@ static bool PebPatchHeapFlags(PEB_CURRENT* peb, HANDLE hProcess)
|
|||
|
||||
*force_flags = 0;
|
||||
|
||||
if (WriteProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE)
|
||||
if(WriteProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -167,10 +167,10 @@ static bool FixPebInProcess(HANDLE hProcess)
|
|||
|
||||
void* AddressOfPEB = GetPEBLocation(hProcess);
|
||||
|
||||
if (!AddressOfPEB)
|
||||
if(!AddressOfPEB)
|
||||
return false;
|
||||
|
||||
if (ReadProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead))
|
||||
if(ReadProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead))
|
||||
{
|
||||
myPEB.BeingDebugged = FALSE;
|
||||
myPEB.NtGlobalFlag &= ~0x70;
|
||||
|
|
@ -194,7 +194,7 @@ static bool FixPebInProcess(HANDLE hProcess)
|
|||
|
||||
PebPatchHeapFlags(&myPEB, hProcess);
|
||||
|
||||
if (WriteProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead))
|
||||
if(WriteProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ static HANDLE WINAPI ProcessIdToHandle(IN DWORD dwProcessId)
|
|||
PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION,
|
||||
&ObjectAttributes,
|
||||
&ClientId);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail */
|
||||
BaseSetLastNTError(Status);
|
||||
|
|
@ -51,7 +51,7 @@ static NTSTATUS CreateThreadSkipAttach(IN HANDLE ProcessHandle, IN PUSER_THREAD_
|
|||
NTSTATUS Status;
|
||||
HANDLE hThread;
|
||||
|
||||
typedef NTSTATUS(NTAPI *t_NtCreateThreadEx)(
|
||||
typedef NTSTATUS(NTAPI * t_NtCreateThreadEx)(
|
||||
PHANDLE /* ThreadHandle */,
|
||||
ACCESS_MASK /* DesiredAccess */,
|
||||
POBJECT_ATTRIBUTES /* ObjectAttributes */,
|
||||
|
|
@ -66,7 +66,7 @@ static NTSTATUS CreateThreadSkipAttach(IN HANDLE ProcessHandle, IN PUSER_THREAD_
|
|||
);
|
||||
|
||||
auto p_NtCreateThreadEx = (t_NtCreateThreadEx)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");
|
||||
if (p_NtCreateThreadEx)
|
||||
if(p_NtCreateThreadEx)
|
||||
{
|
||||
// Based on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/339263/16/client/crashpad_client_win.cc#697
|
||||
Status = p_NtCreateThreadEx(&hThread,
|
||||
|
|
@ -96,7 +96,7 @@ static NTSTATUS CreateThreadSkipAttach(IN HANDLE ProcessHandle, IN PUSER_THREAD_
|
|||
&ClientId);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
NtClose(hThread);
|
||||
}
|
||||
|
|
@ -108,11 +108,11 @@ static NTSTATUS NTAPI DbgUiIssueRemoteBreakin_(IN HANDLE Process)
|
|||
{
|
||||
PUSER_THREAD_START_ROUTINE RemoteBreakFunction = (PUSER_THREAD_START_ROUTINE)DbgUiRemoteBreakin;
|
||||
LPVOID RemoteMemory = VirtualAllocEx(Process, 0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READ);
|
||||
if (RemoteMemory)
|
||||
if(RemoteMemory)
|
||||
{
|
||||
SIZE_T written = 0;
|
||||
unsigned char payload[] = { 0xCC, 0xC3 };
|
||||
if (WriteProcessMemory(Process, RemoteMemory, payload, sizeof(payload), &written))
|
||||
if(WriteProcessMemory(Process, RemoteMemory, payload, sizeof(payload), &written))
|
||||
{
|
||||
RemoteBreakFunction = (PUSER_THREAD_START_ROUTINE)RemoteMemory;
|
||||
}
|
||||
|
|
@ -133,11 +133,11 @@ static NTSTATUS NTAPI DbgUiDebugActiveProcess_(IN HANDLE Process)
|
|||
return Status;
|
||||
|
||||
#if 0
|
||||
if (NT_SUCCESS(Status))
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
/* Now break-in the process */
|
||||
Status = DbgUiIssueRemoteBreakin_(Process);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
/* We couldn't break-in, cancel debugging */
|
||||
DbgUiStopDebugging(Process);
|
||||
|
|
@ -151,7 +151,7 @@ static NTSTATUS NTAPI DbgUiDebugActiveProcess_(IN HANDLE Process)
|
|||
|
||||
static NTSTATUS NTAPI DbgUiConnectToDbg_()
|
||||
{
|
||||
if (NtCurrentTeb()->DbgSsReserved[1] != NULL)
|
||||
if(NtCurrentTeb()->DbgSsReserved[1] != NULL)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
|
|
@ -164,7 +164,7 @@ BOOL WINAPI DebugActiveProcess_(IN DWORD dwProcessId)
|
|||
{
|
||||
/* Connect to the debugger */
|
||||
NTSTATUS Status = DbgUiConnectToDbg_();
|
||||
if (!NT_SUCCESS(Status))
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
|
|
@ -172,7 +172,7 @@ BOOL WINAPI DebugActiveProcess_(IN DWORD dwProcessId)
|
|||
|
||||
/* Get the process handle */
|
||||
HANDLE Handle = ProcessIdToHandle(dwProcessId);
|
||||
if (!Handle)
|
||||
if(!Handle)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -184,7 +184,7 @@ BOOL WINAPI DebugActiveProcess_(IN DWORD dwProcessId)
|
|||
NtClose(Handle);
|
||||
|
||||
/* Check if debugging worked */
|
||||
if (!NT_SUCCESS(Status))
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail */
|
||||
BaseSetLastNTError(Status);
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ BOOL WINAPI DllMain(
|
|||
_In_ LPVOID lpvReserved
|
||||
)
|
||||
{
|
||||
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||
if(fdwReason == DLL_PROCESS_ATTACH)
|
||||
emu.engineHandle = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -7,10 +7,10 @@
|
|||
#else
|
||||
# ifndef ZYDIS_EXPORT
|
||||
# ifdef Zydis_EXPORTS
|
||||
/* We are building this library */
|
||||
/* We are building this library */
|
||||
# define ZYDIS_EXPORT
|
||||
# else
|
||||
/* We are using this library */
|
||||
/* We are using this library */
|
||||
# define ZYDIS_EXPORT
|
||||
# endif
|
||||
# endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
AStyleHelper\AStyleHelper.exe Silent
|
||||
Loading…
Reference in New Issue