mirror of https://github.com/x64dbg/GleeBug
AStyle format
This commit is contained in:
parent
63a6668514
commit
30217c92d4
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>
|
||||
|
|
@ -21,7 +21,7 @@ namespace GleeBug
|
|||
_In_ HANDLE /*hProcess*/,
|
||||
_Out_ LPDWORD /*lpFlags*/,
|
||||
_Out_ PBOOL /*lpPermanent*/
|
||||
);
|
||||
);
|
||||
static auto GPDP = GETPROCESSDEPPOLICY(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetProcessDEPPolicy"));
|
||||
if(GPDP)
|
||||
{
|
||||
|
|
@ -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
|
||||
//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);
|
||||
|
|
@ -200,7 +200,7 @@ namespace GleeBug
|
|||
|
||||
//However the following situations may occur:
|
||||
// The instruction we singlestep to is a software breakpoint, which may execute a callback, that can :
|
||||
// -actually delete a memory breakpoint that takes this page into account
|
||||
// -actually delete a memory breakpoint that takes this page into account
|
||||
// -add more memory breakpoints
|
||||
//The solution: We just try to see if the page is mapped into memoryBreakpointPages. If the page is in deed being used by any memory breakpoint,
|
||||
// then we ought to restore the protection.
|
||||
|
|
@ -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);
|
||||
|
|
@ -238,12 +238,12 @@ namespace GleeBug
|
|||
const auto info = foundInfo->second;
|
||||
|
||||
//TODO: check if the right type is accessed (ExceptionInformation[0])
|
||||
//FIXED:
|
||||
//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);
|
||||
|
|
@ -253,34 +253,34 @@ namespace GleeBug
|
|||
//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))
|
||||
{
|
||||
mContinueStatus = DBG_CONTINUE;
|
||||
//We restore the protection
|
||||
if (!mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.OldProtect))
|
||||
{
|
||||
sprintf_s(error, "MemProtect failed on 0x%p", (void*)pageAddr);
|
||||
cbInternalError(error);
|
||||
}
|
||||
|
||||
mThread->StepInternal(std::bind([this, pageAddr]()
|
||||
{
|
||||
//seek out the page address
|
||||
auto found_page = mProcess->memoryBreakpointPages.find(pageAddr);
|
||||
if (found_page == mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
//no page being used by bpx? Then just return
|
||||
return;
|
||||
}
|
||||
mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect);
|
||||
return;
|
||||
}));
|
||||
return;
|
||||
if(((pageProperties.Type & 0x2) != 0) && ((pageProperties.Type & 0x1) == 0))
|
||||
{
|
||||
mContinueStatus = DBG_CONTINUE;
|
||||
//We restore the protection
|
||||
if(!mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.OldProtect))
|
||||
{
|
||||
sprintf_s(error, "MemProtect failed on 0x%p", (void*)pageAddr);
|
||||
cbInternalError(error);
|
||||
}
|
||||
else if (((pageProperties.Type & 0x1) != 0))
|
||||
|
||||
mThread->StepInternal(std::bind([this, pageAddr]()
|
||||
{
|
||||
//seek out the page address
|
||||
auto found_page = mProcess->memoryBreakpointPages.find(pageAddr);
|
||||
if(found_page == mProcess->memoryBreakpointPages.end())
|
||||
{
|
||||
//no page being used by bpx? Then just return
|
||||
return;
|
||||
}
|
||||
mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect);
|
||||
return;
|
||||
}));
|
||||
return;
|
||||
}
|
||||
else if(((pageProperties.Type & 0x1) != 0))
|
||||
{
|
||||
//We are fine if the breakpoint is on Access and somethine other than a read occurred.
|
||||
}
|
||||
|
|
@ -296,12 +296,12 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ASSUME:
|
||||
|
|
@ -314,7 +314,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 +323,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);
|
||||
|
|
@ -336,7 +336,7 @@ namespace GleeBug
|
|||
//-memoryBreakpointPages was in deed consistent with this memory address that generated the exception (The data structure wasn't corrupted somehow)
|
||||
//So our new technique basically checks if the page address is still inside memoryBreakpointRanges structure. If this is true, we simply apply the NewProtect.
|
||||
//Wide variety of possible scenarios:
|
||||
//-Bpx on this page and bpx is not singleshot: In the case of PAGE_GUARD page protection (handled by this exception handler), if the page permission map persists, we simply
|
||||
//-Bpx on this page and bpx is not singleshot: In the case of PAGE_GUARD page protection (handled by this exception handler), if the page permission map persists, we simply
|
||||
// enforce the newProtect because this page belongs to a breakpoint somewhere.
|
||||
//-Bpx is singleshot: Then it was deleted by the end of this call. If the refcount is zero, then we dont find the page on the Memory map, so assume no more memory breakpoints happen there.
|
||||
// therefore, we do not enforce new protection.
|
||||
|
|
@ -345,14 +345,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 +371,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
|
||||
//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 +384,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);
|
||||
|
|
@ -392,7 +392,7 @@ namespace GleeBug
|
|||
|
||||
//However the following situations may occur:
|
||||
// The instruction we singlestep to is a software breakpoint, which may execute a callback, that can :
|
||||
// -actually delete a memory breakpoint that takes this page into account
|
||||
// -actually delete a memory breakpoint that takes this page into account
|
||||
// -add more memory breakpoints
|
||||
//The solution: We just try to see if the page is mapped into memoryBreakpointPages. If the page is in deed being used by any memory breakpoint,
|
||||
// then we ought to restore the protection.
|
||||
|
|
@ -400,7 +400,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 +417,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);
|
||||
|
|
@ -430,9 +430,9 @@ namespace GleeBug
|
|||
const auto info = foundInfo->second;
|
||||
|
||||
//TODO: check if the right type is accessed (ExceptionInformation[0])
|
||||
//FIXED:
|
||||
//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 +449,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 +470,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 +479,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);
|
||||
|
|
@ -492,7 +492,7 @@ namespace GleeBug
|
|||
//-memoryBreakpointPages was in deed consistent with this memory address that generated the exception (The data structure wasn't corrupted somehow)
|
||||
//So our new technique basically checks if the page address is still inside memoryBreakpointRanges structure. If this is true, we simply apply the NewProtect.
|
||||
//Wide variety of possible scenarios:
|
||||
//-Bpx on this page and bpx is not singleshot: In the case of PAGE_GUARD page protection (handled by this exception handler), if the page permission map persists, we simply
|
||||
//-Bpx on this page and bpx is not singleshot: In the case of PAGE_GUARD page protection (handled by this exception handler), if the page permission map persists, we simply
|
||||
// enforce the newProtect because this page belongs to a breakpoint somewhere.
|
||||
//-Bpx is singleshot: Then it was deleted by the end of this call. If the refcount is zero, then we dont find the page on the Memory map, so assume no more memory breakpoints happen there.
|
||||
// therefore, we do not enforce new protection.
|
||||
|
|
@ -501,14 +501,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 +526,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 +543,7 @@ namespace GleeBug
|
|||
}
|
||||
|
||||
//call the unhandled exception callback
|
||||
if (mContinueStatus == DBG_EXCEPTION_NOT_HANDLED)
|
||||
if(mContinueStatus == DBG_EXCEPTION_NOT_HANDLED)
|
||||
cbUnhandledException(exceptionRecord, firstChance);
|
||||
}
|
||||
};
|
||||
|
|
@ -17,18 +17,20 @@ namespace GleeBug
|
|||
|
||||
//process housekeeping
|
||||
mProcesses.insert({ mDebugEvent.dwProcessId,
|
||||
std::make_unique<Process>(createProcess.hProcess,
|
||||
mDebugEvent.dwProcessId,
|
||||
mDebugEvent.dwThreadId,
|
||||
createProcess) });
|
||||
std::make_unique<Process>(createProcess.hProcess,
|
||||
mDebugEvent.dwProcessId,
|
||||
mDebugEvent.dwThreadId,
|
||||
createProcess)
|
||||
});
|
||||
mProcess = mProcesses.find(mDebugEvent.dwProcessId)->second.get();
|
||||
|
||||
//thread housekeeping (main thread is created implicitly)
|
||||
mProcess->threads.insert({ mDebugEvent.dwThreadId,
|
||||
std::make_unique<Thread>(createProcess.hThread,
|
||||
mDebugEvent.dwThreadId,
|
||||
createProcess.lpThreadLocalBase,
|
||||
createProcess.lpStartAddress) });
|
||||
std::make_unique<Thread>(createProcess.hThread,
|
||||
mDebugEvent.dwThreadId,
|
||||
createProcess.lpThreadLocalBase,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@ namespace GleeBug
|
|||
{
|
||||
//thread housekeeping
|
||||
mProcess->threads.insert({ mDebugEvent.dwThreadId,
|
||||
std::make_unique<Thread>(createThread.hThread,
|
||||
mDebugEvent.dwThreadId,
|
||||
createThread.lpThreadLocalBase,
|
||||
createThread.lpStartAddress) });
|
||||
std::make_unique<Thread>(createThread.hThread,
|
||||
mDebugEvent.dwThreadId,
|
||||
createThread.lpThreadLocalBase,
|
||||
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,8 +5,8 @@ namespace GleeBug
|
|||
bool Process::SetBreakpoint(ptr address, bool singleshoot, SoftwareType type)
|
||||
{
|
||||
//check the address
|
||||
if (!MemIsValidPtr(address) ||
|
||||
breakpoints.find({ BreakpointType::Software, address }) != breakpoints.end())
|
||||
if(!MemIsValidPtr(address) ||
|
||||
breakpoints.find({ BreakpointType::Software, address }) != breakpoints.end())
|
||||
return false;
|
||||
|
||||
//setup the breakpoint information struct
|
||||
|
|
@ -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) ||
|
||||
breakpoints.find({ BreakpointType::Hardware, address }) != breakpoints.end())
|
||||
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;
|
||||
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,35 +369,35 @@ 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);
|
||||
}
|
||||
|
||||
|
|
@ -410,7 +410,7 @@ namespace GleeBug
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@ namespace GleeBug
|
|||
void Thread::StepInto(const StepCallback & cbStep)
|
||||
{
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -13,17 +13,17 @@ namespace GleeBug
|
|||
}
|
||||
|
||||
bool Debugger::Init(const wchar_t* szFilePath,
|
||||
const wchar_t* szCommandLine,
|
||||
const wchar_t* szCurrentDirectory,
|
||||
bool newConsole,
|
||||
bool startSuspended)
|
||||
const wchar_t* szCommandLine,
|
||||
const wchar_t* szCurrentDirectory,
|
||||
bool newConsole,
|
||||
bool startSuspended)
|
||||
{
|
||||
memset(&mMainStartupInfo, 0, sizeof(mMainStartupInfo));
|
||||
memset(&mMainProcess, 0, sizeof(mMainProcess));
|
||||
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;
|
||||
|
|
@ -38,15 +38,15 @@ namespace GleeBug
|
|||
}
|
||||
|
||||
bool result = !!CreateProcessW(szFileNameCreateProcess,
|
||||
szCommandLineCreateProcess,
|
||||
nullptr,
|
||||
nullptr,
|
||||
FALSE,
|
||||
DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | (newConsole ? CREATE_NEW_CONSOLE : 0) | (startSuspended ? CREATE_SUSPENDED : 0),
|
||||
nullptr,
|
||||
szCurrentDirectory,
|
||||
&mMainStartupInfo,
|
||||
&mMainProcess);
|
||||
szCommandLineCreateProcess,
|
||||
nullptr,
|
||||
nullptr,
|
||||
FALSE,
|
||||
DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | (newConsole ? CREATE_NEW_CONSOLE : 0) | (startSuspended ? CREATE_SUSPENDED : 0),
|
||||
nullptr,
|
||||
szCurrentDirectory,
|
||||
&mMainStartupInfo,
|
||||
&mMainProcess);
|
||||
|
||||
delete[] szCreateWithCmdLine;
|
||||
mAttachedToProcess = false;
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -37,10 +37,10 @@ namespace GleeBug
|
|||
\return true if the debuggee was started correctly, false otherwise.
|
||||
*/
|
||||
bool Init(const wchar_t* szFilePath,
|
||||
const wchar_t* szCommandLine,
|
||||
const wchar_t* szCurrentDirectory,
|
||||
bool newConsole = true,
|
||||
bool startSuspended = false);
|
||||
const wchar_t* szCommandLine,
|
||||
const wchar_t* szCurrentDirectory,
|
||||
bool newConsole = true,
|
||||
bool startSuspended = false);
|
||||
|
||||
/**
|
||||
\brief Attach to a debuggee.
|
||||
|
|
@ -287,7 +287,7 @@ namespace GleeBug
|
|||
bool mBreakDebugger = false;
|
||||
DEBUG_EVENT mDebugEvent;
|
||||
ProcessMap mProcesses;
|
||||
bool mIsRunning = false; //TODO: needs a dedicated critical section to prevent ContinueDebugEvent and change of registers to race
|
||||
bool mIsRunning = false; //TODO: needs a dedicated critical section to prevent ContinueDebugEvent and change of registers to race
|
||||
bool mIsDebugging = false;
|
||||
bool mDetach = false;
|
||||
bool mDetachAndBreak = false;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ namespace GleeBug
|
|||
{
|
||||
BufferFile::BufferFile(void* data, uint32 size)
|
||||
: File(nullptr),
|
||||
mData(data),
|
||||
mSize(size)
|
||||
mData(data),
|
||||
mSize(size)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ namespace GleeBug
|
|||
{
|
||||
File::File(const wchar_t* szFileName, File::Mode mode)
|
||||
: mFileName(szFileName ? szFileName : L""),
|
||||
mMode(mode),
|
||||
mhFile(INVALID_HANDLE_VALUE)
|
||||
mMode(mode),
|
||||
mhFile(INVALID_HANDLE_VALUE)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ namespace GleeBug
|
|||
public:
|
||||
explicit Section(uint16 index, uint32 alignment, Region<IMAGE_SECTION_HEADER> & headers, Region<uint8> beforeData, Region<uint8> data)
|
||||
: mIndex(index),
|
||||
mAlignment(alignment),
|
||||
mHeaders(headers),
|
||||
mBeforeData(beforeData),
|
||||
mData(data)
|
||||
mAlignment(alignment),
|
||||
mHeaders(headers),
|
||||
mBeforeData(beforeData),
|
||||
mData(data)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ namespace GleeBug
|
|||
*/
|
||||
explicit Region(std::vector<uint8>* data, uint32 offset, uint32 count = 1)
|
||||
: mData(data),
|
||||
mOffset(offset),
|
||||
mCount(count)
|
||||
mOffset(offset),
|
||||
mCount(count)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ namespace GleeBug
|
|||
*/
|
||||
T* Data() const
|
||||
{
|
||||
if (!Valid())
|
||||
if(!Valid())
|
||||
return nullptr;
|
||||
return (T*)(mData->data() + mOffset);
|
||||
}
|
||||
|
|
@ -83,9 +83,9 @@ namespace GleeBug
|
|||
bool Valid() const
|
||||
{
|
||||
return mOffset != INVALID_VALUE &&
|
||||
mCount != INVALID_VALUE &&
|
||||
mData && mData->data() &&
|
||||
mOffset + mCount * sizeof(T) <= mData->size();
|
||||
mCount != INVALID_VALUE &&
|
||||
mData && mData->data() &&
|
||||
mOffset + mCount * sizeof(T) <= mData->size();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -107,7 +107,7 @@ namespace GleeBug
|
|||
/**
|
||||
\brief Returns Data().
|
||||
*/
|
||||
T* operator ()() const
|
||||
T* operator()() const
|
||||
{
|
||||
return Data();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ protected:
|
|||
void cbMemoryBreakpoint2(const BreakpointInfo & info)
|
||||
{
|
||||
printf("Reached memory breakpoint#2! GIP: 0x%p\n",
|
||||
(void*)Registers(mThread->hThread).Gip());
|
||||
(void*)Registers(mThread->hThread).Gip());
|
||||
}
|
||||
|
||||
void cbMemoryBreakpoint(const BreakpointInfo & info)
|
||||
|
|
@ -22,11 +22,11 @@ protected:
|
|||
Registers registers(mThread->hThread);
|
||||
|
||||
printf("Reached memory breakpoint! GIP: 0x%p\n",
|
||||
(void*)registers.Gip());
|
||||
(void*)registers.Gip());
|
||||
|
||||
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]);
|
||||
}
|
||||
|
|
@ -53,14 +53,14 @@ protected:
|
|||
{
|
||||
Registers registers(mThread->hThread);
|
||||
printf("Reached entry breakpoint! GIP: 0x%p\n",
|
||||
(void*)registers.Gip());
|
||||
(void*)registers.Gip());
|
||||
#ifdef _WIN64
|
||||
auto addr = registers.Rbx();
|
||||
#else
|
||||
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...");
|
||||
|
|
@ -82,8 +82,8 @@ protected:
|
|||
{
|
||||
Registers registers(mThread->hThread);
|
||||
printf("Reached entry hardware breakpoint! GIP: 0x%p\n",
|
||||
(void*)registers.Gip());
|
||||
if (mProcess->DeleteHardwareBreakpoint(info.address))
|
||||
(void*)registers.Gip());
|
||||
if(mProcess->DeleteHardwareBreakpoint(info.address))
|
||||
printf("Entry hardware breakpoint deleted!\n");
|
||||
else
|
||||
printf("Failed to delete entry hardware breakpoint...\n");
|
||||
|
|
@ -91,7 +91,7 @@ protected:
|
|||
{
|
||||
Registers registers(mThread->hThread);
|
||||
printf("Step after entry hardware breakpoint! GIP: 0x%p\n",
|
||||
(void*)registers.Gip());
|
||||
(void*)registers.Gip());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -99,15 +99,15 @@ protected:
|
|||
{
|
||||
Registers registers(mThread->hThread);
|
||||
printf("Reached step after system breakpoint, GIP: 0x%p!\n",
|
||||
(void*)registers.Gip());
|
||||
(void*)registers.Gip());
|
||||
}
|
||||
|
||||
void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const Process & process) override
|
||||
{
|
||||
ptr entry = ptr(createProcess.lpStartAddress);
|
||||
printf("Process %d created with entry 0x%p\n",
|
||||
mDebugEvent.dwProcessId,
|
||||
(void*)entry);
|
||||
mDebugEvent.dwProcessId,
|
||||
(void*)entry);
|
||||
/*HardwareSlot slot;
|
||||
if (mProcess->GetFreeHardwareBreakpointSlot(slot))
|
||||
{
|
||||
|
|
@ -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("");
|
||||
}
|
||||
|
|
@ -146,96 +146,96 @@ protected:
|
|||
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const Process & process) override
|
||||
{
|
||||
printf("Process %u terminated with exit code 0x%08X\n",
|
||||
mDebugEvent.dwProcessId,
|
||||
exitProcess.dwExitCode);
|
||||
mDebugEvent.dwProcessId,
|
||||
exitProcess.dwExitCode);
|
||||
}
|
||||
|
||||
void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const Thread & thread) override
|
||||
{
|
||||
printf("Thread %u created with entry 0x%p\n",
|
||||
mDebugEvent.dwThreadId,
|
||||
createThread.lpStartAddress);
|
||||
mDebugEvent.dwThreadId,
|
||||
createThread.lpStartAddress);
|
||||
}
|
||||
|
||||
void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const Thread & thread) override
|
||||
{
|
||||
printf("Thread %u terminated with exit code 0x%08X\n",
|
||||
mDebugEvent.dwThreadId,
|
||||
exitThread.dwExitCode);
|
||||
mDebugEvent.dwThreadId,
|
||||
exitThread.dwExitCode);
|
||||
}
|
||||
|
||||
void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) override
|
||||
{
|
||||
printf("DLL loaded at 0x%p\n",
|
||||
loadDll.lpBaseOfDll);
|
||||
loadDll.lpBaseOfDll);
|
||||
}
|
||||
|
||||
void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll) override
|
||||
{
|
||||
printf("DLL 0x%p unloaded\n",
|
||||
unloadDll.lpBaseOfDll);
|
||||
unloadDll.lpBaseOfDll);
|
||||
}
|
||||
|
||||
void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) override
|
||||
{
|
||||
const char* exceptionType = exceptionInfo.dwFirstChance ? "First Chance" : "Second Chance";
|
||||
printf("%s exception with code 0x%08X at 0x%p\n",
|
||||
exceptionType,
|
||||
exceptionInfo.ExceptionRecord.ExceptionCode,
|
||||
exceptionInfo.ExceptionRecord.ExceptionAddress);
|
||||
for (DWORD i = 0; i < exceptionInfo.ExceptionRecord.NumberParameters; i++)
|
||||
exceptionType,
|
||||
exceptionInfo.ExceptionRecord.ExceptionCode,
|
||||
exceptionInfo.ExceptionRecord.ExceptionAddress);
|
||||
for(DWORD i = 0; i < exceptionInfo.ExceptionRecord.NumberParameters; i++)
|
||||
printf(" ExceptionInformation[%d] = 0x%p\n", i, (void*)exceptionInfo.ExceptionRecord.ExceptionInformation[i]);
|
||||
}
|
||||
|
||||
void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) override
|
||||
{
|
||||
printf("Debug string at 0x%p with length %d\n",
|
||||
debugString.lpDebugStringData,
|
||||
debugString.nDebugStringLength);
|
||||
debugString.lpDebugStringData,
|
||||
debugString.nDebugStringLength);
|
||||
}
|
||||
|
||||
void cbRipEvent(const RIP_INFO & rip) override
|
||||
{
|
||||
printf("RIP event type 0x%X, error 0x%X",
|
||||
rip.dwType,
|
||||
rip.dwError);
|
||||
rip.dwType,
|
||||
rip.dwError);
|
||||
}
|
||||
|
||||
void cbAttachBreakpoint() override
|
||||
{
|
||||
Registers registers(mThread->hThread);
|
||||
printf("Attach breakpoint reached, GIP: 0x%p\n",
|
||||
(void*)registers.Gip());
|
||||
(void*)registers.Gip());
|
||||
}
|
||||
|
||||
void cbSystemBreakpoint() override
|
||||
{
|
||||
Registers registers(mThread->hThread);
|
||||
printf("System breakpoint reached, GIP: 0x%p\n",
|
||||
(void*)registers.Gip());
|
||||
(void*)registers.Gip());
|
||||
mThread->StepInto(this, &MyDebugger::cbStepSystem);
|
||||
}
|
||||
|
||||
void cbInternalError(const std::string & error) override
|
||||
{
|
||||
printf("Internal Error: %s\n",
|
||||
error.c_str());
|
||||
error.c_str());
|
||||
}
|
||||
|
||||
void cbBreakpoint(const BreakpointInfo & info) override
|
||||
{
|
||||
printf("Breakpoint on 0x%p!\n",
|
||||
(void*)info.address);
|
||||
(void*)info.address);
|
||||
}
|
||||
|
||||
void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) override
|
||||
{
|
||||
Registers registers(mThread->hThread);
|
||||
printf("Unhandled exception (%s) 0x%08X on 0x%p, GIP: 0x%p\n",
|
||||
firstChance ? "first chance" : "second chance",
|
||||
exceptionRecord.ExceptionCode,
|
||||
exceptionRecord.ExceptionAddress,
|
||||
(void*)registers.Gip());
|
||||
firstChance ? "first chance" : "second chance",
|
||||
exceptionRecord.ExceptionCode,
|
||||
exceptionRecord.ExceptionAddress,
|
||||
(void*)registers.Gip());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
@ -30,12 +30,12 @@ template<typename T>
|
|||
static void printRegion(const char* str, Region<T> region, bool newline = true)
|
||||
{
|
||||
printf("\n%s (offset: 0x%X, size: 0x%X, v: %s, e: %s)",
|
||||
str,
|
||||
region.Offset(),
|
||||
region.Size(),
|
||||
region.Valid() ? "true" : "false",
|
||||
region.Empty() ? "true" : "false");
|
||||
if (newline)
|
||||
str,
|
||||
region.Offset(),
|
||||
region.Size(),
|
||||
region.Valid() ? "true" : "false",
|
||||
region.Empty() ? "true" : "false");
|
||||
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);
|
||||
}
|
||||
|
|
@ -151,7 +152,7 @@ public:
|
|||
mProcessInfo.dwThreadId = dwMainThreadId;
|
||||
mProcessInfo.hThread = mThreadList[dwMainThreadId];
|
||||
*mAttachProcessInfo = mProcessInfo;
|
||||
|
||||
|
||||
//create process
|
||||
CREATE_PROCESS_DEBUG_INFO createProcess;
|
||||
memset(&createProcess, 0, sizeof(CREATE_PROCESS_DEBUG_INFO));
|
||||
|
|
@ -190,7 +191,7 @@ public:
|
|||
if(!dllName.empty())
|
||||
CloseHandle(loadDll.hFile);
|
||||
}
|
||||
|
||||
|
||||
//create threads
|
||||
for(auto it : mThreadList)
|
||||
{
|
||||
|
|
@ -211,7 +212,7 @@ public:
|
|||
|
||||
//attach breakpoint
|
||||
mCbATTACHBREAKPOINT();
|
||||
|
||||
|
||||
//system breakpoint
|
||||
mCbSYSTEMBREAKPOINT(nullptr);
|
||||
|
||||
|
|
@ -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,23 +573,23 @@ 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
|
||||
auto RVA_ToConvert = AddressIsRVA ?
|
||||
AddressToConvert :
|
||||
AddressToConvert - ImageBase;
|
||||
AddressToConvert :
|
||||
AddressToConvert - ImageBase;
|
||||
|
||||
// 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,14 +653,14 @@ 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()
|
||||
? GetPE32DataW_impl(found->second.pe->GetNtHeaders64(), WhichSection, WhichData, sections)
|
||||
: GetPE32DataW_impl(found->second.pe->GetNtHeaders32(), WhichSection, WhichData, sections);
|
||||
? GetPE32DataW_impl(found->second.pe->GetNtHeaders64(), WhichSection, WhichData, sections)
|
||||
: GetPE32DataW_impl(found->second.pe->GetNtHeaders32(), WhichSection, WhichData, sections);
|
||||
}
|
||||
|
||||
ULONG_PTR GetPE32Data(const char* szFileName, DWORD WhichSection, DWORD WhichData)
|
||||
|
|
@ -670,18 +671,18 @@ 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()
|
||||
? GetPE32DataW_impl(pe.GetNtHeaders64(), WhichSection, WhichData, sections)
|
||||
: GetPE32DataW_impl(pe.GetNtHeaders32(), WhichSection, WhichData, sections);
|
||||
? GetPE32DataW_impl(pe.GetNtHeaders64(), WhichSection, WhichData, sections)
|
||||
: GetPE32DataW_impl(pe.GetNtHeaders32(), WhichSection, WhichData, sections);
|
||||
}
|
||||
|
||||
bool IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA)
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
////
|
||||
|
|
@ -652,15 +653,15 @@ public:
|
|||
|
||||
// Convert to RVA if needed
|
||||
auto RVA_ToConvert = AddressIsRVA ?
|
||||
AddressToConvert :
|
||||
AddressToConvert - ImageBase;
|
||||
AddressToConvert :
|
||||
AddressToConvert - ImageBase;
|
||||
|
||||
// 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;
|
||||
|
|
@ -730,8 +731,8 @@ public:
|
|||
__debugbreak(); //return 0;
|
||||
auto sections = found->second.pe->GetSections();
|
||||
return found->second.pe->IsPe64()
|
||||
? GetPE32DataW_impl(found->second.pe->GetNtHeaders64(), WhichSection, WhichData, sections)
|
||||
: GetPE32DataW_impl(found->second.pe->GetNtHeaders32(), WhichSection, WhichData, sections);
|
||||
? GetPE32DataW_impl(found->second.pe->GetNtHeaders64(), WhichSection, WhichData, sections)
|
||||
: GetPE32DataW_impl(found->second.pe->GetNtHeaders32(), WhichSection, WhichData, sections);
|
||||
}
|
||||
|
||||
ULONG_PTR GetPE32Data(const char* szFileName, DWORD WhichSection, DWORD WhichData)
|
||||
|
|
@ -752,8 +753,8 @@ public:
|
|||
__debugbreak(); //return 0;
|
||||
auto sections = pe.GetSections();
|
||||
return pe.IsPe64()
|
||||
? GetPE32DataW_impl(pe.GetNtHeaders64(), WhichSection, WhichData, sections)
|
||||
: GetPE32DataW_impl(pe.GetNtHeaders32(), WhichSection, WhichData, sections);
|
||||
? GetPE32DataW_impl(pe.GetNtHeaders64(), WhichSection, WhichData, sections)
|
||||
: GetPE32DataW_impl(pe.GetNtHeaders32(), WhichSection, WhichData, sections);
|
||||
}
|
||||
|
||||
bool IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA)
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -782,7 +783,7 @@ public:
|
|||
bool IsBPXEnabled(ULONG_PTR bpxAddress)
|
||||
{
|
||||
return (mProcess->MemIsValidPtr(bpxAddress) &&
|
||||
mProcess->breakpoints.find({ BreakpointType::Software, bpxAddress }) != mProcess->breakpoints.end());
|
||||
mProcess->breakpoints.find({ BreakpointType::Software, bpxAddress }) != mProcess->breakpoints.end());
|
||||
}
|
||||
|
||||
void SetBPXOptions(long DefaultBreakPointType)
|
||||
|
|
@ -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)
|
||||
|
|
@ -819,11 +820,11 @@ public:
|
|||
thread.second->Suspend();
|
||||
}
|
||||
if(!mProcess->SetHardwareBreakpoint(bpxAddress,
|
||||
(HardwareSlot)IndexOfRegister, [bpxCallBack](const BreakpointInfo & info)
|
||||
{
|
||||
(HWBPCALLBACK(bpxCallBack))((const void*)info.address);
|
||||
(HardwareSlot)IndexOfRegister, [bpxCallBack](const BreakpointInfo & info)
|
||||
{
|
||||
(HWBPCALLBACK(bpxCallBack))((const void*)info.address);
|
||||
}, hwtypeFromTitan(bpxType), hwsizeFromTitan(bpxSize)))
|
||||
return false;
|
||||
return false;
|
||||
if(running)
|
||||
{
|
||||
for(auto & thread : mProcess->threads)
|
||||
|
|
@ -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,14 +1286,14 @@ 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 &&
|
||||
GetModuleFileNameW(engineHandle, szDebuggeeName, _countof(szDebuggeeName)) &&
|
||||
TryExtractDllLoader(true);
|
||||
GetModuleFileNameW(engineHandle, szDebuggeeName, _countof(szDebuggeeName)) &&
|
||||
TryExtractDllLoader(true);
|
||||
}
|
||||
|
||||
private: //variables
|
||||
|
|
|
|||
|
|
@ -145,43 +145,43 @@ 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;
|
||||
BOOL Success = _InitializeContext(NULL,
|
||||
CONTEXT_ALL | CONTEXT_XSTATE,
|
||||
NULL,
|
||||
&ContextSize);
|
||||
CONTEXT_ALL | CONTEXT_XSTATE,
|
||||
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;
|
||||
Success = _InitializeContext(Buffer,
|
||||
CONTEXT_ALL | CONTEXT_XSTATE,
|
||||
&Context,
|
||||
&ContextSize);
|
||||
if (Success == FALSE)
|
||||
CONTEXT_ALL | CONTEXT_XSTATE,
|
||||
&Context,
|
||||
&ContextSize);
|
||||
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,43 +206,43 @@ 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;
|
||||
BOOL Success = _InitializeContext(NULL,
|
||||
CONTEXT_ALL | CONTEXT_XSTATE,
|
||||
NULL,
|
||||
&ContextSize);
|
||||
CONTEXT_ALL | CONTEXT_XSTATE,
|
||||
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;
|
||||
Success = _InitializeContext(Buffer,
|
||||
CONTEXT_ALL | CONTEXT_XSTATE,
|
||||
&Context,
|
||||
&ContextSize);
|
||||
if (Success == FALSE)
|
||||
CONTEXT_ALL | CONTEXT_XSTATE,
|
||||
&Context,
|
||||
&ContextSize);
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServiceP
|
|||
{
|
||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
|
||||
DWORDLONG const dwlConditionMask = VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
|
||||
VER_MINORVERSION, VER_GREATER_EQUAL),
|
||||
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||
VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
|
||||
VER_MINORVERSION, VER_GREATER_EQUAL),
|
||||
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||
|
||||
osvi.dwMajorVersion = wMajorVersion;
|
||||
osvi.dwMinorVersion = wMinorVersion;
|
||||
|
|
@ -41,163 +41,163 @@ IsWindowsVistaOrGreater()
|
|||
|
||||
static int getHeapFlagsOffset(bool x64)
|
||||
{
|
||||
if (x64) //x64 offsets
|
||||
{
|
||||
if (IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x70;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0x14;
|
||||
}
|
||||
}
|
||||
else //x86 offsets
|
||||
{
|
||||
if (IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x40;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0x0C;
|
||||
}
|
||||
}
|
||||
if(x64) //x64 offsets
|
||||
{
|
||||
if(IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x70;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0x14;
|
||||
}
|
||||
}
|
||||
else //x86 offsets
|
||||
{
|
||||
if(IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x40;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0x0C;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int getHeapForceFlagsOffset(bool x64)
|
||||
{
|
||||
if (x64) //x64 offsets
|
||||
{
|
||||
if (IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x74;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0x18;
|
||||
}
|
||||
}
|
||||
else //x86 offsets
|
||||
{
|
||||
if (IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x44;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0x10;
|
||||
}
|
||||
}
|
||||
if(x64) //x64 offsets
|
||||
{
|
||||
if(IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x74;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0x18;
|
||||
}
|
||||
}
|
||||
else //x86 offsets
|
||||
{
|
||||
if(IsWindowsVistaOrGreater())
|
||||
{
|
||||
return 0x44;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0x10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void* GetPEBLocation_(HANDLE hProcess)
|
||||
{
|
||||
ULONG RequiredLen = 0;
|
||||
void* PebAddress = 0;
|
||||
PROCESS_BASIC_INFORMATION myProcessBasicInformation[5] = { 0 };
|
||||
ULONG RequiredLen = 0;
|
||||
void* PebAddress = 0;
|
||||
PROCESS_BASIC_INFORMATION myProcessBasicInformation[5] = { 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)
|
||||
{
|
||||
PebAddress = (void*)myProcessBasicInformation->PebBaseAddress;
|
||||
}
|
||||
}
|
||||
if(NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, sizeof(PROCESS_BASIC_INFORMATION), &RequiredLen) == 0)
|
||||
{
|
||||
PebAddress = (void*)myProcessBasicInformation->PebBaseAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, RequiredLen, &RequiredLen) == 0)
|
||||
{
|
||||
PebAddress = (void*)myProcessBasicInformation->PebBaseAddress;
|
||||
}
|
||||
}
|
||||
|
||||
return PebAddress;
|
||||
return PebAddress;
|
||||
}
|
||||
|
||||
static bool PebPatchHeapFlags(PEB_CURRENT* peb, HANDLE hProcess)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
const auto is_x64 = true;
|
||||
const auto is_x64 = true;
|
||||
#else
|
||||
const auto is_x64 = false;
|
||||
const auto is_x64 = false;
|
||||
#endif
|
||||
|
||||
std::vector<PVOID> heaps;
|
||||
heaps.resize(peb->NumberOfHeaps);
|
||||
std::vector<PVOID> heaps;
|
||||
heaps.resize(peb->NumberOfHeaps);
|
||||
|
||||
if (ReadProcessMemory(hProcess, (PVOID)peb->ProcessHeaps, (PVOID)heaps.data(), heaps.size() * sizeof(PVOID), nullptr) == FALSE)
|
||||
return 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++)
|
||||
{
|
||||
if (ReadProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE)
|
||||
return false;
|
||||
std::basic_string<uint8_t> heap;
|
||||
heap.resize(0x100); // hacky
|
||||
for(DWORD i = 0; i < peb->NumberOfHeaps; i++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// Default heap.
|
||||
*flags &= HEAP_GROWABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Flags from RtlCreateHeap/HeapCreate.
|
||||
*flags &= (HEAP_GROWABLE | HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_CREATE_ENABLE_EXECUTE);
|
||||
}
|
||||
if(i == 0)
|
||||
{
|
||||
// Default heap.
|
||||
*flags &= HEAP_GROWABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Flags from RtlCreateHeap/HeapCreate.
|
||||
*flags &= (HEAP_GROWABLE | HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_CREATE_ENABLE_EXECUTE);
|
||||
}
|
||||
|
||||
*force_flags = 0;
|
||||
*force_flags = 0;
|
||||
|
||||
if (WriteProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE)
|
||||
return false;
|
||||
}
|
||||
if(WriteProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FixPebInProcess(HANDLE hProcess)
|
||||
{
|
||||
PEB_CURRENT myPEB = { 0 };
|
||||
SIZE_T ueNumberOfBytesRead = 0;
|
||||
void* heapFlagsAddress = 0;
|
||||
DWORD heapFlags = 0;
|
||||
void* heapForceFlagsAddress = 0;
|
||||
DWORD heapForceFlags = 0;
|
||||
PEB_CURRENT myPEB = { 0 };
|
||||
SIZE_T ueNumberOfBytesRead = 0;
|
||||
void* heapFlagsAddress = 0;
|
||||
DWORD heapFlags = 0;
|
||||
void* heapForceFlagsAddress = 0;
|
||||
DWORD heapForceFlags = 0;
|
||||
|
||||
void* AddressOfPEB = GetPEBLocation(hProcess);
|
||||
void* AddressOfPEB = GetPEBLocation(hProcess);
|
||||
|
||||
if (!AddressOfPEB)
|
||||
return false;
|
||||
if(!AddressOfPEB)
|
||||
return false;
|
||||
|
||||
if (ReadProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead))
|
||||
{
|
||||
myPEB.BeingDebugged = FALSE;
|
||||
myPEB.NtGlobalFlag &= ~0x70;
|
||||
if(ReadProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead))
|
||||
{
|
||||
myPEB.BeingDebugged = FALSE;
|
||||
myPEB.NtGlobalFlag &= ~0x70;
|
||||
|
||||
#ifdef _WIN64
|
||||
heapFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapFlagsOffset(true));
|
||||
heapForceFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapForceFlagsOffset(true));
|
||||
heapFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapFlagsOffset(true));
|
||||
heapForceFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapForceFlagsOffset(true));
|
||||
#else
|
||||
heapFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapFlagsOffset(false));
|
||||
heapForceFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapForceFlagsOffset(false));
|
||||
heapFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapFlagsOffset(false));
|
||||
heapForceFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapForceFlagsOffset(false));
|
||||
#endif //_WIN64
|
||||
|
||||
ReadProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0);
|
||||
ReadProcessMemory(hProcess, heapForceFlagsAddress, &heapForceFlags, sizeof(DWORD), 0);
|
||||
ReadProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0);
|
||||
ReadProcessMemory(hProcess, heapForceFlagsAddress, &heapForceFlags, sizeof(DWORD), 0);
|
||||
|
||||
heapFlags &= HEAP_GROWABLE;
|
||||
heapForceFlags = 0;
|
||||
heapFlags &= HEAP_GROWABLE;
|
||||
heapForceFlags = 0;
|
||||
|
||||
WriteProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0);
|
||||
WriteProcessMemory(hProcess, heapForceFlagsAddress, &heapForceFlags, sizeof(DWORD), 0);
|
||||
WriteProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0);
|
||||
WriteProcessMemory(hProcess, heapForceFlagsAddress, &heapForceFlags, sizeof(DWORD), 0);
|
||||
|
||||
PebPatchHeapFlags(&myPEB, hProcess);
|
||||
PebPatchHeapFlags(&myPEB, hProcess);
|
||||
|
||||
if (WriteProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if(WriteProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -23,12 +23,12 @@ static HANDLE WINAPI ProcessIdToHandle(IN DWORD dwProcessId)
|
|||
ClientId.UniqueProcess = UlongToHandle(dwProcessId);
|
||||
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
||||
Status = NtOpenProcess(&Handle,
|
||||
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
|
||||
PROCESS_VM_WRITE | PROCESS_VM_READ |
|
||||
PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION,
|
||||
&ObjectAttributes,
|
||||
&ClientId);
|
||||
if (!NT_SUCCESS(Status))
|
||||
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
|
||||
PROCESS_VM_WRITE | PROCESS_VM_READ |
|
||||
PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION,
|
||||
&ObjectAttributes,
|
||||
&ClientId);
|
||||
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 */,
|
||||
|
|
@ -63,40 +63,40 @@ static NTSTATUS CreateThreadSkipAttach(IN HANDLE ProcessHandle, IN PUSER_THREAD_
|
|||
SIZE_T /* StackSize */,
|
||||
SIZE_T /* MaximumStackSize */,
|
||||
PPS_ATTRIBUTE_LIST /* AttributeList */
|
||||
);
|
||||
);
|
||||
|
||||
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,
|
||||
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
|
||||
nullptr,
|
||||
ProcessHandle,
|
||||
StartRoutine,
|
||||
Argument,
|
||||
THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH,
|
||||
0,
|
||||
0x4000 /* PAGE_SIZE * 4 */,
|
||||
0x4000,
|
||||
nullptr);
|
||||
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
|
||||
nullptr,
|
||||
ProcessHandle,
|
||||
StartRoutine,
|
||||
Argument,
|
||||
THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH,
|
||||
0,
|
||||
0x4000 /* PAGE_SIZE * 4 */,
|
||||
0x4000,
|
||||
nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLIENT_ID ClientId;
|
||||
Status = RtlCreateUserThread(ProcessHandle,
|
||||
NULL,
|
||||
FALSE,
|
||||
0,
|
||||
0x4000,
|
||||
0x4000 /* PAGE_SIZE * 4 */,
|
||||
StartRoutine,
|
||||
Argument,
|
||||
&hThread,
|
||||
&ClientId);
|
||||
NULL,
|
||||
FALSE,
|
||||
0,
|
||||
0x4000,
|
||||
0x4000 /* PAGE_SIZE * 4 */,
|
||||
StartRoutine,
|
||||
Argument,
|
||||
&hThread,
|
||||
&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;
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 106
|
||||
|
|
|
|||
|
|
@ -7,16 +7,16 @@
|
|||
#else
|
||||
# ifndef ZYDIS_EXPORT
|
||||
# ifdef Zydis_EXPORTS
|
||||
/* We are building this library */
|
||||
# define ZYDIS_EXPORT
|
||||
/* We are building this library */
|
||||
# define ZYDIS_EXPORT
|
||||
# else
|
||||
/* We are using this library */
|
||||
# define ZYDIS_EXPORT
|
||||
/* We are using this library */
|
||||
# define ZYDIS_EXPORT
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef ZYDIS_NO_EXPORT
|
||||
# define ZYDIS_NO_EXPORT
|
||||
# define ZYDIS_NO_EXPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue