Merge pull request #68 from gmh5225/Branch_AStyle

AStyle format
This commit is contained in:
Duncan Ogilvie 2022-06-29 12:31:38 +02:00 committed by GitHub
commit 69be313fac
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 862 additions and 788 deletions

BIN
AStyleHelper/AStyle.dll Normal file

Binary file not shown.

Binary file not shown.

View File

@ -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>

View File

@ -21,7 +21,7 @@ namespace GleeBug
_In_ HANDLE /*hProcess*/, _In_ HANDLE /*hProcess*/,
_Out_ LPDWORD /*lpFlags*/, _Out_ LPDWORD /*lpFlags*/,
_Out_ PBOOL /*lpPermanent*/ _Out_ PBOOL /*lpPermanent*/
); );
static auto GPDP = GETPROCESSDEPPOLICY(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetProcessDEPPolicy")); static auto GPDP = GETPROCESSDEPPOLICY(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetProcessDEPPolicy"));
if(GPDP) if(GPDP)
{ {
@ -75,7 +75,7 @@ namespace GleeBug
void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) 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 //set internal status
mThread->isInternalStepping = false; mThread->isInternalStepping = false;
@ -84,7 +84,7 @@ namespace GleeBug
//call the internal step callback //call the internal step callback
mThread->cbInternalStep(); mThread->cbInternalStep();
} }
if (mThread->isSingleStepping) //handle single step if(mThread->isSingleStepping) //handle single step
{ {
//set internal status //set internal status
mThread->isSingleStepping = false; mThread->isSingleStepping = false;
@ -96,7 +96,7 @@ namespace GleeBug
//call the user callbacks //call the user callbacks
auto cbStepCopy = mThread->stepCallbacks; auto cbStepCopy = mThread->stepCallbacks;
mThread->stepCallbacks.clear(); mThread->stepCallbacks.clear();
for (auto cbStep : cbStepCopy) for(auto cbStep : cbStepCopy)
cbStep(); cbStep();
} }
else //handle hardware breakpoint single step exceptions else //handle hardware breakpoint single step exceptions
@ -112,22 +112,22 @@ namespace GleeBug
ptr dr6 = registers.Dr6(); ptr dr6 = registers.Dr6();
HardwareSlot breakpointSlot; HardwareSlot breakpointSlot;
ptr breakpointAddress; ptr breakpointAddress;
if (exceptionAddress == registers.Dr0() || dr6 & 0x1) if(exceptionAddress == registers.Dr0() || dr6 & 0x1)
{ {
breakpointAddress = registers.Dr0(); breakpointAddress = registers.Dr0();
breakpointSlot = HardwareSlot::Dr0; breakpointSlot = HardwareSlot::Dr0;
} }
else if (exceptionAddress == registers.Dr1() || dr6 & 0x2) else if(exceptionAddress == registers.Dr1() || dr6 & 0x2)
{ {
breakpointAddress = registers.Dr1(); breakpointAddress = registers.Dr1();
breakpointSlot = HardwareSlot::Dr1; breakpointSlot = HardwareSlot::Dr1;
} }
else if (exceptionAddress == registers.Dr2() || dr6 & 0x4) else if(exceptionAddress == registers.Dr2() || dr6 & 0x4)
{ {
breakpointAddress = registers.Dr2(); breakpointAddress = registers.Dr2();
breakpointSlot = HardwareSlot::Dr2; breakpointSlot = HardwareSlot::Dr2;
} }
else if (exceptionAddress == registers.Dr3() || dr6 & 0x8) else if(exceptionAddress == registers.Dr3() || dr6 & 0x8)
{ {
breakpointAddress = registers.Dr3(); breakpointAddress = registers.Dr3();
breakpointSlot = HardwareSlot::Dr3; breakpointSlot = HardwareSlot::Dr3;
@ -137,10 +137,10 @@ namespace GleeBug
//find the breakpoint in the internal structures //find the breakpoint in the internal structures
auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Hardware, breakpointAddress }); auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Hardware, breakpointAddress });
if (foundInfo == mProcess->breakpoints.end()) if(foundInfo == mProcess->breakpoints.end())
return; //not a valid hardware breakpoint return; //not a valid hardware breakpoint
const auto info = foundInfo->second; const auto info = foundInfo->second;
if (info.internal.hardware.slot != breakpointSlot) if(info.internal.hardware.slot != breakpointSlot)
return; //not a valid hardware breakpoint return; //not a valid hardware breakpoint
//set continue status //set continue status
@ -151,7 +151,7 @@ namespace GleeBug
mThread->StepInternal(std::bind([this, info]() mThread->StepInternal(std::bind([this, info]()
{ {
//only restore if the breakpoint still exists //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); 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 //call the user callback
auto foundCallback = mProcess->breakpointCallbacks.find({ BreakpointType::Hardware, info.address }); auto foundCallback = mProcess->breakpointCallbacks.find({ BreakpointType::Hardware, info.address });
if (foundCallback != mProcess->breakpointCallbacks.end()) if(foundCallback != mProcess->breakpointCallbacks.end())
foundCallback->second(info); foundCallback->second(info);
//delete the breakpoint if it is singleshoot //delete the breakpoint if it is singleshoot
if (info.singleshoot) if(info.singleshoot)
mProcess->DeleteGenericBreakpoint(info); mProcess->DeleteGenericBreakpoint(info);
} }
@ -179,11 +179,11 @@ namespace GleeBug
//check if the exception address is directly in the range of a memory breakpoint //check if the exception address is directly in the range of a memory breakpoint
auto foundRange = mProcess->memoryBreakpointRanges.find(Range(exceptionAddress, exceptionAddress)); 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)); 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) //(this means that by our fault the program generated an exception, we should clean it)
mContinueStatus = DBG_CONTINUE; mContinueStatus = DBG_CONTINUE;
@ -192,7 +192,7 @@ namespace GleeBug
const auto pBaseAddr = foundPage->first; const auto pBaseAddr = foundPage->first;
//We restore the protection //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); sprintf_s(error, "MemProtect failed on 0x%p", (void*)foundPage->first);
cbInternalError(error); cbInternalError(error);
@ -208,7 +208,7 @@ namespace GleeBug
{ {
//seek out the page address //seek out the page address
auto found_page = mProcess->memoryBreakpointPages.find(pBaseAddr); 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 //no page being used by bpx? Then just return
return; return;
@ -225,7 +225,7 @@ namespace GleeBug
exceptionAddress is indeed inside a breakpoint range you have defined. exceptionAddress is indeed inside a breakpoint range you have defined.
*/ */
auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Memory, foundRange->first }); 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); sprintf_s(error, "inconsistent memory breakpoint at 0x%p", (void*)exceptionAddress);
cbInternalError(error); cbInternalError(error);
@ -240,47 +240,46 @@ namespace GleeBug
//TODO: check if the right type is accessed (ExceptionInformation[0]) //TODO: check if the right type is accessed (ExceptionInformation[0])
//FIXED: //FIXED:
auto bpxPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1)); auto bpxPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1));
auto pageAddr = bpxPage->first; if(bpxPage == mProcess->memoryBreakpointPages.end())
auto pageProperties = bpxPage->second;
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))); sprintf_s(error, "Process::memoryBreakPointPages data structure is incosistent, should dump page at 0x%p", (void*)(exceptionAddress & ~(PAGE_SIZE - 1)));
cbInternalError(error); cbInternalError(error);
return; return;
} }
auto pageAddr = bpxPage->first;
auto pageProperties = bpxPage->second;
//TODO: If I only have a page with Read bp and the exception was not on read, I don't execute the callback. Because since this was implemented with PAGE_GUARD, writtes or executes still trigger //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. //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. //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. //The bpx is solely on read.
if (((pageProperties.Type & 0x2) != 0) && ((pageProperties.Type & 0x1) == 0)) if(((pageProperties.Type & 0x2) != 0) && ((pageProperties.Type & 0x1) == 0))
{ {
mContinueStatus = DBG_CONTINUE; mContinueStatus = DBG_CONTINUE;
//We restore the protection //We restore the protection
if (!mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.OldProtect)) if(!mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.OldProtect))
{ {
sprintf_s(error, "MemProtect failed on 0x%p", (void*)pageAddr); sprintf_s(error, "MemProtect failed on 0x%p", (void*)pageAddr);
cbInternalError(error); 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;
} }
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. //We are fine if the breakpoint is on Access and somethine other than a read occurred.
} }
@ -296,7 +295,7 @@ namespace GleeBug
{ {
//The generated exception is on read. //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 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; return;
} }
@ -314,7 +313,7 @@ namespace GleeBug
//TODO: execute the user callback (if present) //TODO: execute the user callback (if present)
//FIXED: //FIXED:
auto bpxCb = mProcess->breakpointCallbacks.find({ BreakpointType::Memory, info.address }); auto bpxCb = mProcess->breakpointCallbacks.find({ BreakpointType::Memory, info.address });
if (bpxCb != mProcess->breakpointCallbacks.end()) if(bpxCb != mProcess->breakpointCallbacks.end())
{ {
bpxCb->second(info); bpxCb->second(info);
} }
@ -323,7 +322,7 @@ namespace GleeBug
mContinueStatus = DBG_CONTINUE; mContinueStatus = DBG_CONTINUE;
//TODO: single step and restore page protection //TODO: single step and restore page protection
//FIXED: //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); sprintf_s(error, "MemProtect failed on 0x%p", (void*)pageAddr);
cbInternalError(error); cbInternalError(error);
@ -345,14 +344,14 @@ namespace GleeBug
//Check if the memory page is mapped //Check if the memory page is mapped
auto found_page = mProcess->memoryBreakpointPages.find(pageAddr); 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); mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect);
} }
return; return;
})); }));
if (info.singleshoot) if(info.singleshoot)
{ {
mProcess->DeleteMemoryBreakpoint(exceptionAddress); mProcess->DeleteMemoryBreakpoint(exceptionAddress);
} }
@ -371,11 +370,11 @@ namespace GleeBug
//check if the exception address is directly in the range of a memory breakpoint //check if the exception address is directly in the range of a memory breakpoint
auto foundRange = mProcess->memoryBreakpointRanges.find(Range(exceptionAddress, exceptionAddress)); 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)); 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) //(this means that by our fault the program generated an exception, we should clean it)
mContinueStatus = DBG_CONTINUE; mContinueStatus = DBG_CONTINUE;
@ -384,7 +383,7 @@ namespace GleeBug
const auto pBaseAddr = foundPage->first; const auto pBaseAddr = foundPage->first;
//We restore the protection //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); sprintf_s(error, "MemProtect failed on 0x%p", (void*)foundPage->first);
cbInternalError(error); cbInternalError(error);
@ -400,7 +399,7 @@ namespace GleeBug
{ {
//seek out the page address //seek out the page address
auto found_page = mProcess->memoryBreakpointPages.find(pBaseAddr); 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 //no page being used by bpx? Then just return
return; return;
@ -417,7 +416,7 @@ namespace GleeBug
exceptionAddress is indeed inside a breakpoint range you have defined. exceptionAddress is indeed inside a breakpoint range you have defined.
*/ */
auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Memory, foundRange->first }); 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); sprintf_s(error, "inconsistent memory breakpoint at 0x%p", (void*)exceptionAddress);
cbInternalError(error); cbInternalError(error);
@ -432,7 +431,7 @@ namespace GleeBug
//TODO: check if the right type is accessed (ExceptionInformation[0]) //TODO: check if the right type is accessed (ExceptionInformation[0])
//FIXED: //FIXED:
auto bpxPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1)); 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))); sprintf_s(error, "Process::memoryBreakPointPages data structure is incosistent, should dump page at 0x%p", (void*)(exceptionAddress & ~(PAGE_SIZE - 1)));
cbInternalError(error); cbInternalError(error);
@ -449,13 +448,13 @@ namespace GleeBug
*/ */
//ExceptionInformation[0] should be considered as 1 or 8, because these are for exceptions generated on write or execute. //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. //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. //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; 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. //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; return;
@ -470,7 +469,7 @@ namespace GleeBug
//TODO: execute the user callback (if present) //TODO: execute the user callback (if present)
//FIXED: //FIXED:
auto bpxCb = mProcess->breakpointCallbacks.find({ BreakpointType::Memory, info.address }); auto bpxCb = mProcess->breakpointCallbacks.find({ BreakpointType::Memory, info.address });
if (bpxCb != mProcess->breakpointCallbacks.end()) if(bpxCb != mProcess->breakpointCallbacks.end())
{ {
bpxCb->second(info); bpxCb->second(info);
} }
@ -479,7 +478,7 @@ namespace GleeBug
mContinueStatus = DBG_CONTINUE; mContinueStatus = DBG_CONTINUE;
//TODO: single step and restore page protection //TODO: single step and restore page protection
//FIXED: //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); sprintf_s(error, "MemProtect failed on 0x%p", (void*)pageAddr);
cbInternalError(error); cbInternalError(error);
@ -501,14 +500,14 @@ namespace GleeBug
//Check if the memory page is mapped //Check if the memory page is mapped
auto found_page = mProcess->memoryBreakpointPages.find(pageAddr); 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); mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect);
} }
return; return;
})); }));
if (info.singleshoot) if(info.singleshoot)
{ {
mProcess->DeleteMemoryBreakpoint(exceptionAddress); mProcess->DeleteMemoryBreakpoint(exceptionAddress);
} }
@ -526,7 +525,7 @@ namespace GleeBug
cbExceptionEvent(exceptionInfo); cbExceptionEvent(exceptionInfo);
//dispatch the exception (https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx) //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: case STATUS_BREAKPOINT:
exceptionBreakpoint(exceptionRecord, firstChance); exceptionBreakpoint(exceptionRecord, firstChance);
@ -543,7 +542,7 @@ namespace GleeBug
} }
//call the unhandled exception callback //call the unhandled exception callback
if (mContinueStatus == DBG_EXCEPTION_NOT_HANDLED) if(mContinueStatus == DBG_EXCEPTION_NOT_HANDLED)
cbUnhandledException(exceptionRecord, firstChance); cbUnhandledException(exceptionRecord, firstChance);
} }
}; };

View File

@ -17,18 +17,20 @@ namespace GleeBug
//process housekeeping //process housekeeping
mProcesses.insert({ mDebugEvent.dwProcessId, mProcesses.insert({ mDebugEvent.dwProcessId,
std::make_unique<Process>(createProcess.hProcess, std::make_unique<Process>(createProcess.hProcess,
mDebugEvent.dwProcessId, mDebugEvent.dwProcessId,
mDebugEvent.dwThreadId, mDebugEvent.dwThreadId,
createProcess) }); createProcess)
});
mProcess = mProcesses.find(mDebugEvent.dwProcessId)->second.get(); mProcess = mProcesses.find(mDebugEvent.dwProcessId)->second.get();
//thread housekeeping (main thread is created implicitly) //thread housekeeping (main thread is created implicitly)
mProcess->threads.insert({ mDebugEvent.dwThreadId, mProcess->threads.insert({ mDebugEvent.dwThreadId,
std::make_unique<Thread>(createProcess.hThread, std::make_unique<Thread>(createProcess.hThread,
mDebugEvent.dwThreadId, mDebugEvent.dwThreadId,
createProcess.lpThreadLocalBase, createProcess.lpThreadLocalBase,
createProcess.lpStartAddress) }); createProcess.lpStartAddress)
});
mThread = mProcess->thread = mProcess->threads.find(mDebugEvent.dwThreadId)->second.get(); mThread = mProcess->thread = mProcess->threads.find(mDebugEvent.dwThreadId)->second.get();
//call the debug event callback //call the debug event callback
@ -39,14 +41,14 @@ namespace GleeBug
CloseHandle(createProcess.hFile); CloseHandle(createProcess.hFile);
//call attach breakpoint after process creation //call attach breakpoint after process creation
if (attachBreakpoint) if(attachBreakpoint)
cbAttachBreakpoint(); cbAttachBreakpoint();
} }
void Debugger::exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess) void Debugger::exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess)
{ {
//check if the terminated process is the main debuggee //check if the terminated process is the main debuggee
if (mDebugEvent.dwProcessId == mMainProcess.dwProcessId) if(mDebugEvent.dwProcessId == mMainProcess.dwProcessId)
mBreakDebugger = true; mBreakDebugger = true;
//call the debug event callback //call the debug event callback

View File

@ -6,10 +6,11 @@ namespace GleeBug
{ {
//thread housekeeping //thread housekeeping
mProcess->threads.insert({ mDebugEvent.dwThreadId, mProcess->threads.insert({ mDebugEvent.dwThreadId,
std::make_unique<Thread>(createThread.hThread, std::make_unique<Thread>(createThread.hThread,
mDebugEvent.dwThreadId, mDebugEvent.dwThreadId,
createThread.lpThreadLocalBase, createThread.lpThreadLocalBase,
createThread.lpStartAddress) }); createThread.lpStartAddress)
});
//set the current thread //set the current thread
mThread = mProcess->thread = mProcess->threads.find(mDebugEvent.dwThreadId)->second.get(); mThread = mProcess->thread = mProcess->threads.find(mDebugEvent.dwThreadId)->second.get();

View File

@ -12,38 +12,38 @@ namespace GleeBug
mDetachAndBreak = false; mDetachAndBreak = false;
//use correct WaitForDebugEvent function //use correct WaitForDebugEvent function
typedef BOOL(WINAPI *MYWAITFORDEBUGEVENT)( typedef BOOL(WINAPI * MYWAITFORDEBUGEVENT)(
_Out_ LPDEBUG_EVENT lpDebugEvent, _Out_ LPDEBUG_EVENT lpDebugEvent,
_In_ DWORD dwMilliseconds _In_ DWORD dwMilliseconds
); );
static auto WFDEX = MYWAITFORDEBUGEVENT(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "WaitForDebugEventEx")); static auto WFDEX = MYWAITFORDEBUGEVENT(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "WaitForDebugEventEx"));
static auto MyWaitForDebugEvent = WFDEX ? WFDEX : MYWAITFORDEBUGEVENT(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "WaitForDebugEvent")); static auto MyWaitForDebugEvent = WFDEX ? WFDEX : MYWAITFORDEBUGEVENT(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "WaitForDebugEvent"));
if (!MyWaitForDebugEvent) if(!MyWaitForDebugEvent)
{ {
cbInternalError("MyWaitForDebugEvent not set!"); cbInternalError("MyWaitForDebugEvent not set!");
return; return;
} }
while (!mBreakDebugger) while(!mBreakDebugger)
{ {
//wait for a debug event //wait for a debug event
mIsRunning = true; mIsRunning = true;
if (!MyWaitForDebugEvent(&mDebugEvent, 100)) if(!MyWaitForDebugEvent(&mDebugEvent, 100))
{ {
if (mDetach) if(mDetach)
{ {
if (!UnsafeDetach()) if(!UnsafeDetach())
cbInternalError("Debugger::Detach failed!"); cbInternalError("Debugger::Detach failed!");
break; break;
} }
#if 0 #if 0
// Fix based on work by https://github.com/number201724 // 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.dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT;
mDebugEvent.dwProcessId = mMainProcess.dwProcessId; mDebugEvent.dwProcessId = mMainProcess.dwProcessId;
mDebugEvent.dwThreadId = mMainProcess.dwThreadId; 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; mDebugEvent.u.ExitProcess.dwExitCode = 0xFFFFFFFF;
} }
#endif #endif
@ -60,11 +60,11 @@ namespace GleeBug
//set the current process and thread //set the current process and thread
auto processFound = mProcesses.find(mDebugEvent.dwProcessId); auto processFound = mProcesses.find(mDebugEvent.dwProcessId);
if (processFound != mProcesses.end()) if(processFound != mProcesses.end())
{ {
mProcess = processFound->second.get(); mProcess = processFound->second.get();
auto threadFound = mProcess->threads.find(mDebugEvent.dwThreadId); auto threadFound = mProcess->threads.find(mDebugEvent.dwThreadId);
if (threadFound != mProcess->threads.end()) if(threadFound != mProcess->threads.end())
{ {
mThread = mProcess->thread = threadFound->second.get(); mThread = mProcess->thread = threadFound->second.get();
} }
@ -76,7 +76,7 @@ namespace GleeBug
else else
{ {
mThread = nullptr; mThread = nullptr;
if (mProcess) if(mProcess)
{ {
mProcess->thread = nullptr; mProcess->thread = nullptr;
mProcess = nullptr; mProcess = nullptr;
@ -87,7 +87,7 @@ namespace GleeBug
cbPreDebugEvent(mDebugEvent); cbPreDebugEvent(mDebugEvent);
//dispatch the debug event (documented here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms679302(v=vs.85).aspx) //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: case CREATE_PROCESS_DEBUG_EVENT:
createProcessEvent(mDebugEvent.u.CreateProcessInfo); createProcessEvent(mDebugEvent.u.CreateProcessInfo);
@ -125,27 +125,27 @@ namespace GleeBug
cbPostDebugEvent(mDebugEvent); cbPostDebugEvent(mDebugEvent);
//execute the delayed-detach //execute the delayed-detach
if (mDetachAndBreak) if(mDetachAndBreak)
{ {
if (!UnsafeDetachAndBreak()) if(!UnsafeDetachAndBreak())
cbInternalError("Debugger::DetachAndBreak failed!"); cbInternalError("Debugger::DetachAndBreak failed!");
break; break;
} }
//clear trap flag when set by GleeBug (to prevent an EXCEPTION_SINGLE_STEP after detach) //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; Registers(mThread->hThread, CONTEXT_CONTROL).TrapFlag = false;
} }
//continue the debug event //continue the debug event
if (!ContinueDebugEvent(mDebugEvent.dwProcessId, mDebugEvent.dwThreadId, mContinueStatus)) if(!ContinueDebugEvent(mDebugEvent.dwProcessId, mDebugEvent.dwThreadId, mContinueStatus))
break; break;
if (mDetach || mDetachAndBreak) if(mDetach || mDetachAndBreak)
{ {
if (!UnsafeDetach()) if(!UnsafeDetach())
cbInternalError("Debugger::Detach failed!"); cbInternalError("Debugger::Detach failed!");
break; break;
} }

View File

@ -5,8 +5,8 @@ namespace GleeBug
bool Process::SetBreakpoint(ptr address, bool singleshoot, SoftwareType type) bool Process::SetBreakpoint(ptr address, bool singleshoot, SoftwareType type)
{ {
//check the address //check the address
if (!MemIsValidPtr(address) || if(!MemIsValidPtr(address) ||
breakpoints.find({ BreakpointType::Software, address }) != breakpoints.end()) breakpoints.find({ BreakpointType::Software, address }) != breakpoints.end())
return false; return false;
//setup the breakpoint information struct //setup the breakpoint information struct
@ -16,7 +16,7 @@ namespace GleeBug
info.type = BreakpointType::Software; info.type = BreakpointType::Software;
//determine breakpoint byte and size from the type //determine breakpoint byte and size from the type
switch (type) switch(type)
{ {
case SoftwareType::ShortInt3: case SoftwareType::ShortInt3:
info.internal.software.newbytes[0] = 0xCC; info.internal.software.newbytes[0] = 0xCC;
@ -28,10 +28,10 @@ namespace GleeBug
} }
//read/write the breakpoint //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; 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; return false;
FlushInstructionCache(hProcess, nullptr, 0); FlushInstructionCache(hProcess, nullptr, 0);
@ -45,10 +45,10 @@ namespace GleeBug
bool Process::SetBreakpoint(ptr address, const BreakpointCallback & cbBreakpoint, bool singleshoot, SoftwareType type) bool Process::SetBreakpoint(ptr address, const BreakpointCallback & cbBreakpoint, bool singleshoot, SoftwareType type)
{ {
//check if a callback on this address was already found //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; return false;
//set the breakpoint //set the breakpoint
if (!SetBreakpoint(address, singleshoot, type)) if(!SetBreakpoint(address, singleshoot, type))
return false; return false;
//insert the callback //insert the callback
breakpointCallbacks.insert({ { BreakpointType::Software, address }, cbBreakpoint }); breakpointCallbacks.insert({ { BreakpointType::Software, address }, cbBreakpoint });
@ -59,12 +59,12 @@ namespace GleeBug
{ {
//find the breakpoint //find the breakpoint
auto found = breakpoints.find({ BreakpointType::Software, address }); auto found = breakpoints.find({ BreakpointType::Software, address });
if (found == breakpoints.end()) if(found == breakpoints.end())
return false; return false;
const auto & info = found->second; const auto & info = found->second;
//restore the breakpoint bytes //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; return false;
FlushInstructionCache(hProcess, nullptr, 0); FlushInstructionCache(hProcess, nullptr, 0);
@ -78,9 +78,9 @@ namespace GleeBug
bool Process::GetFreeHardwareBreakpointSlot(HardwareSlot & slot) const bool Process::GetFreeHardwareBreakpointSlot(HardwareSlot & slot) const
{ {
//find a free hardware breakpoint slot //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); slot = HardwareSlot(i);
return true; return true;
@ -92,15 +92,15 @@ namespace GleeBug
bool Process::SetHardwareBreakpoint(ptr address, HardwareSlot slot, HardwareType type, HardwareSize size, bool singleshoot) bool Process::SetHardwareBreakpoint(ptr address, HardwareSlot slot, HardwareType type, HardwareSize size, bool singleshoot)
{ {
//check the address //check the address
if (!MemIsValidPtr(address) || if(!MemIsValidPtr(address) ||
breakpoints.find({ BreakpointType::Hardware, address }) != breakpoints.end()) breakpoints.find({ BreakpointType::Hardware, address }) != breakpoints.end())
return false; return false;
//attempt to set the hardware breakpoint in every thread //attempt to set the hardware breakpoint in every thread
bool success = true; 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; success = false;
break; break;
@ -108,9 +108,9 @@ namespace GleeBug
} }
//if setting failed, unset all //if setting failed, unset all
if (!success) if(!success)
{ {
for (auto & thread : threads) for(auto & thread : threads)
thread.second->DeleteHardwareBreakpoint(slot); thread.second->DeleteHardwareBreakpoint(slot);
return false; return false;
} }
@ -137,10 +137,10 @@ namespace GleeBug
bool Process::SetHardwareBreakpoint(ptr address, HardwareSlot slot, const BreakpointCallback & cbBreakpoint, HardwareType type, HardwareSize size, bool singleshoot) 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 //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; return false;
//set the hardware breakpoint //set the hardware breakpoint
if (!SetHardwareBreakpoint(address, slot, type, size, singleshoot)) if(!SetHardwareBreakpoint(address, slot, type, size, singleshoot))
return false; return false;
//insert the callback //insert the callback
breakpointCallbacks.insert({ { BreakpointType::Hardware, address }, cbBreakpoint }); breakpointCallbacks.insert({ { BreakpointType::Hardware, address }, cbBreakpoint });
@ -151,7 +151,7 @@ namespace GleeBug
{ {
//find the hardware breakpoint //find the hardware breakpoint
auto found = breakpoints.find({ BreakpointType::Hardware, address }); auto found = breakpoints.find({ BreakpointType::Hardware, address });
if (found == breakpoints.end()) if(found == breakpoints.end())
return false; return false;
const auto & info = found->second; const auto & info = found->second;
@ -160,9 +160,9 @@ namespace GleeBug
//delete the hardware breakpoint from the registers //delete the hardware breakpoint from the registers
bool success = true; 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; success = false;
} }
@ -198,7 +198,7 @@ namespace GleeBug
//These settings can trigger access violation. //These settings can trigger access violation.
DWORD dwBase = dwAccess & 0xFF; DWORD dwBase = dwAccess & 0xFF;
DWORD dwHigh = dwAccess & 0xFFFFFF00; DWORD dwHigh = dwAccess & 0xFFFFFF00;
switch (dwBase) switch(dwBase)
{ {
case PAGE_EXECUTE: case PAGE_EXECUTE:
return dwHigh | PAGE_READONLY; return dwHigh | PAGE_READONLY;
@ -214,7 +214,7 @@ namespace GleeBug
static DWORD RemoveWriteAccess(DWORD dwAccess) static DWORD RemoveWriteAccess(DWORD dwAccess)
{ {
DWORD dwBase = dwAccess & 0xFF; DWORD dwBase = dwAccess & 0xFF;
switch (dwBase) switch(dwBase)
{ {
case PAGE_READWRITE: case PAGE_READWRITE:
case PAGE_EXECUTE_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) //TODO: handle PAGE_NOACCESS and such correctly (since it cannot be combined with PAGE_GUARD)
auto found = memoryBreakpointPages.find(page); auto found = memoryBreakpointPages.find(page);
if (found == memoryBreakpointPages.end()) if(found == memoryBreakpointPages.end())
{ {
data.Refcount = 1; data.Refcount = 1;
switch (type) switch(type)
{ {
case MemoryType::Access: case MemoryType::Access:
case MemoryType::Read: case MemoryType::Read:
@ -253,13 +253,13 @@ namespace GleeBug
data.Type = oldData.Type | uint32(type); //combines new protection data.Type = oldData.Type | uint32(type); //combines new protection
data.OldProtect = oldData.OldProtect; // old protection remains the same data.OldProtect = oldData.OldProtect; // old protection remains the same
data.Refcount = oldData.Refcount + 1; //increment reference count 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 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; data.NewProtect = permanentDep ? RemoveExecuteAccess(RemoveWriteAccess(data.OldProtect)) : data.OldProtect | PAGE_GUARD;
} }
@ -274,12 +274,12 @@ namespace GleeBug
//TODO: error reporting //TODO: error reporting
//basic checks //basic checks
if (!MemIsValidPtr(address) || !size) if(!MemIsValidPtr(address) || !size)
return false; return false;
//check if the range is unused for any previous memory breakpoints //check if the range is unused for any previous memory breakpoints
auto range = Range(address, address + size - 1); auto range = Range(address, address + size - 1);
if (memoryBreakpointRanges.find(range) != memoryBreakpointRanges.end()) if(memoryBreakpointRanges.find(range) != memoryBreakpointRanges.end())
return false; return false;
//change page protections //change page protections
@ -297,17 +297,17 @@ namespace GleeBug
MemoryBreakpointData data; MemoryBreakpointData data;
data.Type = uint32(type); data.Type = uint32(type);
auto alignedAddress = PAGE_ALIGN(address); 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; MEMORY_BASIC_INFORMATION mbi;
if (!VirtualQueryEx(hProcess, LPCVOID(page), &mbi, sizeof(mbi))) if(!VirtualQueryEx(hProcess, LPCVOID(page), &mbi, sizeof(mbi)))
{ {
success = false; success = false;
dprintf("!VirtualQueryEx\n"); dprintf("!VirtualQueryEx\n");
break; break;
} }
data.OldProtect = mbi.Protect; data.OldProtect = mbi.Protect;
if (!SetNewPageProtection(page, data, type)) if(!SetNewPageProtection(page, data, type))
{ {
success = false; success = false;
dprintf("!SetNewPageProtection\n"); dprintf("!SetNewPageProtection\n");
@ -321,15 +321,15 @@ namespace GleeBug
} }
//if changing the page protections failed, attempt to revert all protection changes //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); MemProtect(page.addr, PAGE_SIZE, page.OldProtect);
return false; return false;
} }
//set the page data //set the page data
for (const auto & page : breakpointData) for(const auto & page : breakpointData)
memoryBreakpointPages[page.addr] = page.data; memoryBreakpointPages[page.addr] = page.data;
//setup the breakpoint information struct //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) bool Process::SetMemoryBreakpoint(ptr address, ptr size, const BreakpointCallback & cbBreakpoint, MemoryType type, bool singleshoot)
{ {
//check if a callback on this address was already found //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; return false;
//set the memory breakpoint //set the memory breakpoint
if (!SetMemoryBreakpoint(address, size, type, singleshoot)) if(!SetMemoryBreakpoint(address, size, type, singleshoot))
return false; return false;
//insert the callback //insert the callback
breakpointCallbacks.insert({ { BreakpointType::Memory, address }, cbBreakpoint }); breakpointCallbacks.insert({ { BreakpointType::Memory, address }, cbBreakpoint });
@ -369,48 +369,48 @@ namespace GleeBug
//find the memory breakpoint //find the memory breakpoint
auto found = breakpoints.find({ BreakpointType::Memory, range->first }); auto found = breakpoints.find({ BreakpointType::Memory, range->first });
if (found == breakpoints.end()) if(found == breakpoints.end())
return false; return false;
const auto & info = found->second; const auto & info = found->second;
//delete the memory breakpoint from the pages //delete the memory breakpoint from the pages
bool success = true; bool success = true;
auto alignedAddress = PAGE_ALIGN(info.address); 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); auto foundData = memoryBreakpointPages.find(page);
if (foundData == memoryBreakpointPages.end()) if(foundData == memoryBreakpointPages.end())
continue; //TODO: error reporting continue; //TODO: error reporting
auto & data = foundData->second; auto & data = foundData->second;
DWORD Protect; DWORD Protect;
data.Refcount--; data.Refcount--;
if (data.Refcount) if(data.Refcount)
{ {
//TODO: properly determine the new protection flag //TODO: properly determine the new protection flag
//Are there any other protections left? //Are there any other protections left?
//If so add the guard //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; data.NewProtect = data.OldProtect | PAGE_GUARD;
Protect = data.NewProtect; Protect = data.NewProtect;
} }
else else
Protect = data.OldProtect; Protect = data.OldProtect;
if (!MemProtect(page, PAGE_SIZE, Protect)) if(!MemProtect(page, PAGE_SIZE, Protect))
success = false; success = false;
if (!data.Refcount) if(!data.Refcount)
memoryBreakpointPages.erase(foundData); memoryBreakpointPages.erase(foundData);
} }
//delete the breakpoint from the maps //delete the breakpoint from the maps
breakpoints.erase(found); breakpoints.erase(found);
breakpointCallbacks.erase({ BreakpointType::Hardware, address }); breakpointCallbacks.erase({ BreakpointType::Memory, address });
memoryBreakpointRanges.erase(Range(address, address)); memoryBreakpointRanges.erase(Range(address, address));
return success; return success;
} }
bool Process::DeleteGenericBreakpoint(const BreakpointInfo & info) bool Process::DeleteGenericBreakpoint(const BreakpointInfo & info)
{ {
switch (info.type) switch(info.type)
{ {
case BreakpointType::Software: case BreakpointType::Software:
return DeleteBreakpoint(info.address); return DeleteBreakpoint(info.address);

View File

@ -6,46 +6,46 @@ namespace GleeBug
{ {
//TODO: change page protection if reading failed //TODO: change page protection if reading failed
ptr read; ptr read;
if (!bytesRead) if(!bytesRead)
bytesRead = &read; bytesRead = &read;
return !!ReadProcessMemory(this->hProcess, reinterpret_cast<const void*>(address), buffer, size, (SIZE_T*)bytesRead); 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 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; return false;
//choose the filter method that has the lowest cost //choose the filter method that has the lowest cost
auto start = address; auto start = address;
auto end = start + size; 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; continue;
const auto & info = breakpoint.second; const auto & info = breakpoint.second;
auto curAddress = info.address; 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]; ((uint8*)buffer)[curAddress + j - start] = info.internal.software.oldbytes[j];
} }
} }
} }
else else
{ {
for (ptr i = start; i < end; i++) for(ptr i = start; i < end; i++)
{ {
auto found = softwareBreakpointReferences.find(i); auto found = softwareBreakpointReferences.find(i);
if (found == softwareBreakpointReferences.end()) if(found == softwareBreakpointReferences.end())
continue; continue;
const auto & info = found->second->second; const auto & info = found->second->second;
auto curAddress = info.address; 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]; ((uint8*)buffer)[curAddress + j - start] = info.internal.software.oldbytes[j];
} }
i += info.internal.software.size - 1; i += info.internal.software.size - 1;
@ -58,7 +58,7 @@ namespace GleeBug
bool Process::MemWriteUnsafe(ptr address, const void* buffer, ptr size, ptr* bytesWritten) bool Process::MemWriteUnsafe(ptr address, const void* buffer, ptr size, ptr* bytesWritten)
{ {
ptr written; ptr written;
if (!bytesWritten) if(!bytesWritten)
bytesWritten = &written; bytesWritten = &written;
return !!WriteProcessMemory(this->hProcess, reinterpret_cast<void*>(address), buffer, size, (SIZE_T*)bytesWritten); return !!WriteProcessMemory(this->hProcess, reinterpret_cast<void*>(address), buffer, size, (SIZE_T*)bytesWritten);
} }
@ -79,9 +79,9 @@ namespace GleeBug
{ {
DWORD dwOldProtect; DWORD dwOldProtect;
auto vps = VirtualProtectEx(hProcess, LPVOID(address), size, newProtect, &dwOldProtect); auto vps = VirtualProtectEx(hProcess, LPVOID(address), size, newProtect, &dwOldProtect);
if (!vps) if(!vps)
return false; return false;
if (oldProtect) if(oldProtect)
*oldProtect = dwOldProtect; *oldProtect = dwOldProtect;
return true; return true;
} }
@ -89,7 +89,7 @@ namespace GleeBug
ptr Process::MemFindPattern(ptr data, size_t datasize, const Pattern::WildcardPattern & pattern, bool safe) const ptr Process::MemFindPattern(ptr data, size_t datasize, const Pattern::WildcardPattern & pattern, bool safe) const
{ {
std::vector<uint8> buffer(datasize); std::vector<uint8> buffer(datasize);
if (!MemRead(data, buffer.data(), datasize, nullptr, safe)) if(!MemRead(data, buffer.data(), datasize, nullptr, safe))
return 0; return 0;
auto found = Pattern::Find(buffer.data(), datasize, pattern); auto found = Pattern::Find(buffer.data(), datasize, pattern);
return found == -1 ? 0 : found + data; 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 ptr Process::MemFindPattern(ptr data, size_t datasize, const uint8* pattern, size_t patternsize, bool safe) const
{ {
std::vector<uint8> buffer(datasize); std::vector<uint8> buffer(datasize);
if (!MemRead(data, buffer.data(), datasize, nullptr, safe)) if(!MemRead(data, buffer.data(), datasize, nullptr, safe))
return 0; return 0;
auto found = Pattern::Find(buffer.data(), datasize, pattern, patternsize); auto found = Pattern::Find(buffer.data(), datasize, pattern, patternsize);
return found == -1 ? 0 : found + data; 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) bool Process::MemWritePattern(ptr data, size_t datasize, const Pattern::WildcardPattern & pattern, bool safe)
{ {
std::vector<uint8> buffer(datasize); std::vector<uint8> buffer(datasize);
if (!MemRead(data, buffer.data(), datasize, nullptr, safe)) if(!MemRead(data, buffer.data(), datasize, nullptr, safe))
return false; return false;
Pattern::Write(buffer.data(), datasize, pattern); Pattern::Write(buffer.data(), datasize, pattern);
return MemWrite(data, buffer.data(), datasize, nullptr, safe); 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) bool Process::MemSearchAndReplace(ptr data, size_t datasize, const Pattern::WildcardPattern & searchpattern, const Pattern::WildcardPattern & replacepattern, bool safe)
{ {
std::vector<uint8> buffer(datasize); std::vector<uint8> buffer(datasize);
if (!MemRead(data, buffer.data(), datasize, nullptr, safe)) if(!MemRead(data, buffer.data(), datasize, nullptr, safe))
return false; return false;
if (!Pattern::SearchAndReplace(buffer.data(), datasize, searchpattern, replacepattern)) if(!Pattern::SearchAndReplace(buffer.data(), datasize, searchpattern, replacepattern))
return false; return false;
return MemWrite(data, buffer.data(), datasize, nullptr, safe); return MemWrite(data, buffer.data(), datasize, nullptr, safe);
} }

View File

@ -17,7 +17,7 @@ namespace GleeBug
systemBreakpoint(false), systemBreakpoint(false),
permanentDep(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; hardwareBreakpoints[i].internal.hardware.enabled = false;
} }
@ -25,7 +25,7 @@ namespace GleeBug
{ {
auto gip = Registers(thread->hThread, CONTEXT_CONTROL).Gip(); auto gip = Registers(thread->hThread, CONTEXT_CONTROL).Gip();
unsigned char data[16]; unsigned char data[16];
if (MemReadSafe(gip, data, sizeof(data))) if(MemReadSafe(gip, data, sizeof(data)))
{ {
ZydisInstructionInfo info; ZydisInstructionInfo info;
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
@ -47,7 +47,7 @@ namespace GleeBug
stepOver = (info.attributes & repAttributes) != 0; stepOver = (info.attributes & repAttributes) != 0;
} }
} }
if (stepOver) if(stepOver)
{ {
SetBreakpoint(gip + info.length, [cbStep](const BreakpointInfo & info) SetBreakpoint(gip + info.length, [cbStep](const BreakpointInfo & info)
{ {

View File

@ -57,7 +57,7 @@ namespace GleeBug
*/ */
bool MemRead(ptr address, void* buffer, ptr size, ptr* bytesRead = nullptr, bool safe = true) const 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 MemReadSafe(address, buffer, size, bytesRead);
return MemRead(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) 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 MemWriteSafe(address, buffer, size, bytesWritten);
return MemWriteUnsafe(address, buffer, size, bytesWritten); return MemWriteUnsafe(address, buffer, size, bytesWritten);
} }

View File

@ -41,53 +41,53 @@ namespace GleeBug
static ptr dr7_ptr(const DR7 & dr7) static ptr dr7_ptr(const DR7 & dr7)
{ {
ptr result = 0; ptr result = 0;
if (BITGET(dr7.DR7_MODE[0], 0)) if(BITGET(dr7.DR7_MODE[0], 0))
BITSET(result, 0); BITSET(result, 0);
if (BITGET(dr7.DR7_MODE[0], 1)) if(BITGET(dr7.DR7_MODE[0], 1))
BITSET(result, 1); BITSET(result, 1);
if (BITGET(dr7.DR7_MODE[1], 0)) if(BITGET(dr7.DR7_MODE[1], 0))
BITSET(result, 2); BITSET(result, 2);
if (BITGET(dr7.DR7_MODE[1], 1)) if(BITGET(dr7.DR7_MODE[1], 1))
BITSET(result, 3); BITSET(result, 3);
if (BITGET(dr7.DR7_MODE[2], 0)) if(BITGET(dr7.DR7_MODE[2], 0))
BITSET(result, 4); BITSET(result, 4);
if (BITGET(dr7.DR7_MODE[2], 1)) if(BITGET(dr7.DR7_MODE[2], 1))
BITSET(result, 5); BITSET(result, 5);
if (BITGET(dr7.DR7_MODE[3], 0)) if(BITGET(dr7.DR7_MODE[3], 0))
BITSET(result, 6); BITSET(result, 6);
if (BITGET(dr7.DR7_MODE[3], 1)) if(BITGET(dr7.DR7_MODE[3], 1))
BITSET(result, 7); BITSET(result, 7);
if (BITGET(dr7.DR7_TYPE[0], 0)) if(BITGET(dr7.DR7_TYPE[0], 0))
BITSET(result, 16); BITSET(result, 16);
if (BITGET(dr7.DR7_TYPE[0], 1)) if(BITGET(dr7.DR7_TYPE[0], 1))
BITSET(result, 17); BITSET(result, 17);
if (BITGET(dr7.DR7_SIZE[0], 0)) if(BITGET(dr7.DR7_SIZE[0], 0))
BITSET(result, 18); BITSET(result, 18);
if (BITGET(dr7.DR7_SIZE[0], 1)) if(BITGET(dr7.DR7_SIZE[0], 1))
BITSET(result, 19); BITSET(result, 19);
if (BITGET(dr7.DR7_TYPE[1], 0)) if(BITGET(dr7.DR7_TYPE[1], 0))
BITSET(result, 20); BITSET(result, 20);
if (BITGET(dr7.DR7_TYPE[1], 1)) if(BITGET(dr7.DR7_TYPE[1], 1))
BITSET(result, 21); BITSET(result, 21);
if (BITGET(dr7.DR7_SIZE[1], 0)) if(BITGET(dr7.DR7_SIZE[1], 0))
BITSET(result, 22); BITSET(result, 22);
if (BITGET(dr7.DR7_SIZE[1], 1)) if(BITGET(dr7.DR7_SIZE[1], 1))
BITSET(result, 23); BITSET(result, 23);
if (BITGET(dr7.DR7_TYPE[2], 0)) if(BITGET(dr7.DR7_TYPE[2], 0))
BITSET(result, 24); BITSET(result, 24);
if (BITGET(dr7.DR7_TYPE[2], 1)) if(BITGET(dr7.DR7_TYPE[2], 1))
BITSET(result, 25); BITSET(result, 25);
if (BITGET(dr7.DR7_SIZE[2], 0)) if(BITGET(dr7.DR7_SIZE[2], 0))
BITSET(result, 26); BITSET(result, 26);
if (BITGET(dr7.DR7_SIZE[2], 1)) if(BITGET(dr7.DR7_SIZE[2], 1))
BITSET(result, 27); BITSET(result, 27);
if (BITGET(dr7.DR7_TYPE[3], 0)) if(BITGET(dr7.DR7_TYPE[3], 0))
BITSET(result, 28); BITSET(result, 28);
if (BITGET(dr7.DR7_TYPE[3], 1)) if(BITGET(dr7.DR7_TYPE[3], 1))
BITSET(result, 29); BITSET(result, 29);
if (BITGET(dr7.DR7_SIZE[3], 0)) if(BITGET(dr7.DR7_SIZE[3], 0))
BITSET(result, 30); BITSET(result, 30);
if (BITGET(dr7.DR7_SIZE[3], 1)) if(BITGET(dr7.DR7_SIZE[3], 1))
BITSET(result, 31); BITSET(result, 31);
return result; return result;
} }
@ -96,60 +96,60 @@ namespace GleeBug
{ {
DR7 result; DR7 result;
memset(&result, 0, sizeof(DR7)); memset(&result, 0, sizeof(DR7));
if (BITGET(dr7, 0)) if(BITGET(dr7, 0))
BITSET(result.DR7_MODE[0], 0); BITSET(result.DR7_MODE[0], 0);
if (BITGET(dr7, 1)) if(BITGET(dr7, 1))
BITSET(result.DR7_MODE[0], 1); BITSET(result.DR7_MODE[0], 1);
if (BITGET(dr7, 2)) if(BITGET(dr7, 2))
BITSET(result.DR7_MODE[1], 0); BITSET(result.DR7_MODE[1], 0);
if (BITGET(dr7, 3)) if(BITGET(dr7, 3))
BITSET(result.DR7_MODE[1], 1); BITSET(result.DR7_MODE[1], 1);
if (BITGET(dr7, 4)) if(BITGET(dr7, 4))
BITSET(result.DR7_MODE[2], 0); BITSET(result.DR7_MODE[2], 0);
if (BITGET(dr7, 5)) if(BITGET(dr7, 5))
BITSET(result.DR7_MODE[2], 1); BITSET(result.DR7_MODE[2], 1);
if (BITGET(dr7, 6)) if(BITGET(dr7, 6))
BITSET(result.DR7_MODE[3], 0); BITSET(result.DR7_MODE[3], 0);
if (BITGET(dr7, 7)) if(BITGET(dr7, 7))
BITSET(result.DR7_MODE[3], 1); BITSET(result.DR7_MODE[3], 1);
if (BITGET(dr7, 16)) if(BITGET(dr7, 16))
BITSET(result.DR7_TYPE[0], 0); BITSET(result.DR7_TYPE[0], 0);
if (BITGET(dr7, 17)) if(BITGET(dr7, 17))
BITSET(result.DR7_TYPE[0], 1); BITSET(result.DR7_TYPE[0], 1);
if (BITGET(dr7, 18)) if(BITGET(dr7, 18))
BITSET(result.DR7_SIZE[0], 0); BITSET(result.DR7_SIZE[0], 0);
if (BITGET(dr7, 19)) if(BITGET(dr7, 19))
BITSET(result.DR7_SIZE[0], 1); BITSET(result.DR7_SIZE[0], 1);
if (BITGET(dr7, 20)) if(BITGET(dr7, 20))
BITSET(result.DR7_TYPE[1], 0); BITSET(result.DR7_TYPE[1], 0);
if (BITGET(dr7, 21)) if(BITGET(dr7, 21))
BITSET(result.DR7_TYPE[1], 1); BITSET(result.DR7_TYPE[1], 1);
if (BITGET(dr7, 22)) if(BITGET(dr7, 22))
BITSET(result.DR7_SIZE[1], 0); BITSET(result.DR7_SIZE[1], 0);
if (BITGET(dr7, 23)) if(BITGET(dr7, 23))
BITSET(result.DR7_SIZE[1], 1); BITSET(result.DR7_SIZE[1], 1);
if (BITGET(dr7, 24)) if(BITGET(dr7, 24))
BITSET(result.DR7_TYPE[2], 0); BITSET(result.DR7_TYPE[2], 0);
if (BITGET(dr7, 25)) if(BITGET(dr7, 25))
BITSET(result.DR7_TYPE[2], 1); BITSET(result.DR7_TYPE[2], 1);
if (BITGET(dr7, 26)) if(BITGET(dr7, 26))
BITSET(result.DR7_SIZE[2], 0); BITSET(result.DR7_SIZE[2], 0);
if (BITGET(dr7, 27)) if(BITGET(dr7, 27))
BITSET(result.DR7_SIZE[2], 1); BITSET(result.DR7_SIZE[2], 1);
if (BITGET(dr7, 28)) if(BITGET(dr7, 28))
BITSET(result.DR7_TYPE[3], 0); BITSET(result.DR7_TYPE[3], 0);
if (BITGET(dr7, 29)) if(BITGET(dr7, 29))
BITSET(result.DR7_TYPE[3], 1); BITSET(result.DR7_TYPE[3], 1);
if (BITGET(dr7, 30)) if(BITGET(dr7, 30))
BITSET(result.DR7_SIZE[3], 0); BITSET(result.DR7_SIZE[3], 0);
if (BITGET(dr7, 31)) if(BITGET(dr7, 31))
BITSET(result.DR7_SIZE[3], 1); BITSET(result.DR7_SIZE[3], 1);
return result; return result;
} }
static DR7_SIZE size_dr7(HardwareSize size) static DR7_SIZE size_dr7(HardwareSize size)
{ {
switch (size) switch(size)
{ {
case HardwareSize::SizeByte: case HardwareSize::SizeByte:
return SIZE_1; return SIZE_1;
@ -168,7 +168,7 @@ namespace GleeBug
static DR7_TYPE type_dr7(HardwareType type) static DR7_TYPE type_dr7(HardwareType type)
{ {
switch (type) switch(type)
{ {
case HardwareType::Access: case HardwareType::Access:
return TYPE_READWRITE; return TYPE_READWRITE;
@ -184,13 +184,13 @@ namespace GleeBug
bool Thread::SetHardwareBreakpoint(ptr address, HardwareSlot slot, HardwareType type, HardwareSize size) bool Thread::SetHardwareBreakpoint(ptr address, HardwareSlot slot, HardwareType type, HardwareSize size)
{ {
//check if the alignment is correct //check if the alignment is correct
if ((address % int(size) != 0)) if((address % int(size) != 0))
return false; return false;
Registers registers(hThread, CONTEXT_DEBUG_REGISTERS); Registers registers(hThread, CONTEXT_DEBUG_REGISTERS);
//set the address register //set the address register
switch (slot) switch(slot)
{ {
case HardwareSlot::Dr0: case HardwareSlot::Dr0:
registers.Dr0 = address; registers.Dr0 = address;
@ -224,7 +224,7 @@ namespace GleeBug
Registers registers(hThread, CONTEXT_DEBUG_REGISTERS); Registers registers(hThread, CONTEXT_DEBUG_REGISTERS);
//zero the address register //zero the address register
switch (slot) switch(slot)
{ {
case HardwareSlot::Dr0: case HardwareSlot::Dr0:
registers.Dr0 = 0; registers.Dr0 = 0;

View File

@ -56,7 +56,7 @@ namespace GleeBug
{ {
ptr Registers::Get(R reg) ptr Registers::Get(R reg)
{ {
switch (reg) switch(reg)
{ {
case R::DR0: case R::DR0:
return ptr(mContext.Dr0); return ptr(mContext.Dr0);
@ -258,7 +258,7 @@ namespace GleeBug
void Registers::Set(R reg, ptr value) void Registers::Set(R reg, ptr value)
{ {
switch (reg) switch(reg)
{ {
case R::DR0: case R::DR0:
mContext.Dr0 = value; mContext.Dr0 = value;
@ -556,7 +556,7 @@ namespace GleeBug
void Registers::SetFlag(F flag, bool set) void Registers::SetFlag(F flag, bool set)
{ {
if (set) if(set)
mContext.EFlags |= ptr(flag); mContext.EFlags |= ptr(flag);
else else
mContext.EFlags &= ~ptr(flag); mContext.EFlags &= ~ptr(flag);
@ -564,7 +564,7 @@ namespace GleeBug
void* Registers::getPtr(R reg) void* Registers::getPtr(R reg)
{ {
switch (reg) switch(reg)
{ {
case R::DR0: case R::DR0:
return REGPTR(mContext.Dr0); return REGPTR(mContext.Dr0);

View File

@ -137,7 +137,7 @@ public:
Type Get() const Type Get() const
{ {
auto ptr = (Type*)mRegisters->getPtr(RegisterIndex); auto ptr = (Type*)mRegisters->getPtr(RegisterIndex);
if (ptr) if(ptr)
return *ptr; return *ptr;
return Type(); return Type();
} }
@ -149,7 +149,7 @@ public:
void Set(Type value) void Set(Type value)
{ {
auto ptr = (Type*)mRegisters->getPtr(RegisterIndex); auto ptr = (Type*)mRegisters->getPtr(RegisterIndex);
if (ptr) if(ptr)
*ptr = value; *ptr = value;
} }

View File

@ -108,7 +108,7 @@ namespace GleeBug
{ {
memset(&mContext, 0, sizeof(CONTEXT)); memset(&mContext, 0, sizeof(CONTEXT));
mContext.ContextFlags = ContextFlags; mContext.ContextFlags = ContextFlags;
if (!!GetThreadContext(hThread, &mContext)) if(!!GetThreadContext(hThread, &mContext))
{ {
this->hThread = hThread; this->hThread = hThread;
memcpy(&mOldContext, &mContext, sizeof(CONTEXT)); memcpy(&mOldContext, &mContext, sizeof(CONTEXT));
@ -121,7 +121,7 @@ namespace GleeBug
Registers::~Registers() Registers::~Registers()
{ {
if (hThread && memcmp(&mContext, &mOldContext, sizeof(CONTEXT)) != 0) if(hThread && memcmp(&mContext, &mOldContext, sizeof(CONTEXT)) != 0)
SetThreadContext(hThread, &mContext); SetThreadContext(hThread, &mContext);
} }

View File

@ -25,9 +25,9 @@ namespace GleeBug
StepInto(); StepInto();
auto target = cbStep.target<void()>(); 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!"); puts("duplicate StepInto callback detected!");
return; return;

View File

@ -13,17 +13,17 @@ namespace GleeBug
} }
bool Debugger::Init(const wchar_t* szFilePath, bool Debugger::Init(const wchar_t* szFilePath,
const wchar_t* szCommandLine, const wchar_t* szCommandLine,
const wchar_t* szCurrentDirectory, const wchar_t* szCurrentDirectory,
bool newConsole, bool newConsole,
bool startSuspended) bool startSuspended)
{ {
memset(&mMainStartupInfo, 0, sizeof(mMainStartupInfo)); memset(&mMainStartupInfo, 0, sizeof(mMainStartupInfo));
memset(&mMainProcess, 0, sizeof(mMainProcess)); memset(&mMainProcess, 0, sizeof(mMainProcess));
const wchar_t* szFileNameCreateProcess; const wchar_t* szFileNameCreateProcess;
wchar_t* szCommandLineCreateProcess; wchar_t* szCommandLineCreateProcess;
wchar_t* szCreateWithCmdLine = nullptr; wchar_t* szCreateWithCmdLine = nullptr;
if (szCommandLine == nullptr || !wcslen(szCommandLine)) if(szCommandLine == nullptr || !wcslen(szCommandLine))
{ {
szCommandLineCreateProcess = nullptr; szCommandLineCreateProcess = nullptr;
szFileNameCreateProcess = szFilePath; szFileNameCreateProcess = szFilePath;
@ -38,15 +38,15 @@ namespace GleeBug
} }
bool result = !!CreateProcessW(szFileNameCreateProcess, bool result = !!CreateProcessW(szFileNameCreateProcess,
szCommandLineCreateProcess, szCommandLineCreateProcess,
nullptr, nullptr,
nullptr, nullptr,
FALSE, FALSE,
DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | (newConsole ? CREATE_NEW_CONSOLE : 0) | (startSuspended ? CREATE_SUSPENDED : 0), DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | (newConsole ? CREATE_NEW_CONSOLE : 0) | (startSuspended ? CREATE_SUSPENDED : 0),
nullptr, nullptr,
szCurrentDirectory, szCurrentDirectory,
&mMainStartupInfo, &mMainStartupInfo,
&mMainProcess); &mMainProcess);
delete[] szCreateWithCmdLine; delete[] szCreateWithCmdLine;
mAttachedToProcess = false; mAttachedToProcess = false;
@ -87,7 +87,7 @@ namespace GleeBug
bool Debugger::UnsafeDetachAndBreak() 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; return false;
//trigger an EXCEPTION_SINGLE_STEP in the debuggee //trigger an EXCEPTION_SINGLE_STEP in the debuggee

View File

@ -37,10 +37,10 @@ namespace GleeBug
\return true if the debuggee was started correctly, false otherwise. \return true if the debuggee was started correctly, false otherwise.
*/ */
bool Init(const wchar_t* szFilePath, bool Init(const wchar_t* szFilePath,
const wchar_t* szCommandLine, const wchar_t* szCommandLine,
const wchar_t* szCurrentDirectory, const wchar_t* szCurrentDirectory,
bool newConsole = true, bool newConsole = true,
bool startSuspended = false); bool startSuspended = false);
/** /**
\brief Attach to a debuggee. \brief Attach to a debuggee.

View File

@ -4,8 +4,8 @@ namespace GleeBug
{ {
BufferFile::BufferFile(void* data, uint32 size) BufferFile::BufferFile(void* data, uint32 size)
: File(nullptr), : File(nullptr),
mData(data), mData(data),
mSize(size) mSize(size)
{ {
} }
@ -40,34 +40,34 @@ namespace GleeBug
bool BufferFile::Read(uint32 offset, void* data, uint32 size, uint32* bytesRead) const bool BufferFile::Read(uint32 offset, void* data, uint32 size, uint32* bytesRead) const
{ {
if (offset >= mSize) if(offset >= mSize)
return false; return false;
auto readSize = size; auto readSize = size;
auto result = true; auto result = true;
if (offset + size > mSize) if(offset + size > mSize)
{ {
readSize = mSize - offset; readSize = mSize - offset;
result = false; result = false;
} }
memcpy(data, (uint8*)mData + offset, readSize); memcpy(data, (uint8*)mData + offset, readSize);
if (bytesRead) if(bytesRead)
*bytesRead = readSize; *bytesRead = readSize;
return result; return result;
} }
bool BufferFile::Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten) bool BufferFile::Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten)
{ {
if (offset >= mSize) if(offset >= mSize)
return false; return false;
auto writeSize = size; auto writeSize = size;
auto result = true; auto result = true;
if (offset + size > mSize) if(offset + size > mSize)
{ {
writeSize = mSize - offset; writeSize = mSize - offset;
result = false; result = false;
} }
memcpy((uint8*)mData + offset, data, writeSize); memcpy((uint8*)mData + offset, data, writeSize);
if (bytesWritten) if(bytesWritten)
*bytesWritten = writeSize; *bytesWritten = writeSize;
return result; return result;
} }

View File

@ -4,8 +4,8 @@ namespace GleeBug
{ {
File::File(const wchar_t* szFileName, File::Mode mode) File::File(const wchar_t* szFileName, File::Mode mode)
: mFileName(szFileName ? szFileName : L""), : mFileName(szFileName ? szFileName : L""),
mMode(mode), mMode(mode),
mhFile(INVALID_HANDLE_VALUE) mhFile(INVALID_HANDLE_VALUE)
{ {
} }
@ -31,7 +31,7 @@ namespace GleeBug
void File::Close() void File::Close()
{ {
if (IsOpen()) if(IsOpen())
{ {
CloseHandle(mhFile); CloseHandle(mhFile);
mhFile = INVALID_HANDLE_VALUE; mhFile = INVALID_HANDLE_VALUE;
@ -45,30 +45,30 @@ namespace GleeBug
bool File::Read(uint32 offset, void* data, uint32 size, uint32* bytesRead) const 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; *bytesRead = 0;
return false; return false;
} }
DWORD NumberOfBytesRead = 0; DWORD NumberOfBytesRead = 0;
auto result = !!ReadFile(mhFile, data, size, &NumberOfBytesRead, nullptr); auto result = !!ReadFile(mhFile, data, size, &NumberOfBytesRead, nullptr);
if (bytesRead) if(bytesRead)
*bytesRead = uint32(NumberOfBytesRead); *bytesRead = uint32(NumberOfBytesRead);
return result; return result;
} }
bool File::Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten) 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; *bytesWritten = 0;
return false; return false;
} }
DWORD NumberOfBytesWritten = 0; DWORD NumberOfBytesWritten = 0;
auto result = !!WriteFile(mhFile, data, size, &NumberOfBytesWritten, nullptr); auto result = !!WriteFile(mhFile, data, size, &NumberOfBytesWritten, nullptr);
if (bytesWritten) if(bytesWritten)
*bytesWritten = uint32(NumberOfBytesWritten); *bytesWritten = uint32(NumberOfBytesWritten);
return result; return result;
} }
@ -77,7 +77,7 @@ namespace GleeBug
{ {
//get the access and sharemode flags //get the access and sharemode flags
DWORD access, sharemode; DWORD access, sharemode;
switch (mMode) switch(mMode)
{ {
case ReadOnly: case ReadOnly:
access = GENERIC_READ; access = GENERIC_READ;

View File

@ -6,9 +6,9 @@ namespace GleeBug
{ {
std::string result; std::string result;
result.reserve(patterntext.length()); 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; result += ch;
} }
return result; return result;
@ -19,10 +19,10 @@ namespace GleeBug
std::vector<Byte> pattern; std::vector<Byte> pattern;
auto formattext = FormatPattern(patterntext); auto formattext = FormatPattern(patterntext);
auto len = formattext.length(); auto len = formattext.length();
if (!len) if(!len)
return pattern; return pattern;
if (len % 2) //not a multiple of 2 if(len % 2) //not a multiple of 2
{ {
formattext += '?'; formattext += '?';
len++; len++;
@ -32,20 +32,20 @@ namespace GleeBug
auto hexChToInt = [](char ch) auto hexChToInt = [](char ch)
{ {
if (ch >= '0' && ch <= '9') if(ch >= '0' && ch <= '9')
return ch - '0'; return ch - '0';
if (ch >= 'A' && ch <= 'F') if(ch >= 'A' && ch <= 'F')
return ch - 'A' + 10; return ch - 'A' + 10;
if (ch >= 'a' && ch <= 'f') if(ch >= 'a' && ch <= 'f')
return ch - 'a' + 10; return ch - 'a' + 10;
return -1; return -1;
}; };
Byte newByte; Byte newByte;
auto j = 0; auto j = 0;
for (auto ch : formattext) for(auto ch : formattext)
{ {
if (ch == '?') //wildcard if(ch == '?') //wildcard
{ {
newByte.nibble[j].wildcard = true; //match anything newByte.nibble[j].wildcard = true; //match anything
} }
@ -56,7 +56,7 @@ namespace GleeBug
} }
j++; j++;
if (j == 2) //two nibbles = one byte if(j == 2) //two nibbles = one byte
{ {
j = 0; j = 0;
pattern.push_back(newByte); pattern.push_back(newByte);
@ -72,32 +72,32 @@ namespace GleeBug
auto matched = 0; auto matched = 0;
unsigned char n1 = (byte >> 4) & 0xF; unsigned char n1 = (byte >> 4) & 0xF;
if (pbyte.nibble[0].wildcard) if(pbyte.nibble[0].wildcard)
matched++; matched++;
else if (pbyte.nibble[0].data == n1) else if(pbyte.nibble[0].data == n1)
matched++; matched++;
unsigned char n2 = byte & 0xF; unsigned char n2 = byte & 0xF;
if (pbyte.nibble[1].wildcard) if(pbyte.nibble[1].wildcard)
matched++; matched++;
else if (pbyte.nibble[1].data == n2) else if(pbyte.nibble[1].data == n2)
matched++; matched++;
return matched == 2; return matched == 2;
}; };
auto searchpatternsize = pattern.size(); auto searchpatternsize = pattern.size();
if (!searchpatternsize) if(!searchpatternsize)
return -1; 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++; pos++;
if (pos == searchpatternsize) //everything matched if(pos == searchpatternsize) //everything matched
return i - searchpatternsize + 1; return i - searchpatternsize + 1;
} }
else if (pos > 0) //fix by Computer_Angel else if(pos > 0) //fix by Computer_Angel
{ {
i -= pos; i -= pos;
pos = 0; //reset current pattern position 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) size_t Pattern::Find(const uint8* data, size_t datasize, const uint8* pattern, size_t patternsize)
{ {
if (!patternsize) if(!patternsize)
return -1; return -1;
if (patternsize > datasize) if(patternsize > datasize)
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++; pos++;
if (pos == patternsize) if(pos == patternsize)
return i - patternsize + 1; return i - patternsize + 1;
} }
else if (pos > 0) else if(pos > 0)
{ {
i -= pos; i -= pos;
pos = 0; //reset current pattern position pos = 0; //reset current pattern position
@ -131,32 +131,32 @@ namespace GleeBug
void Pattern::Write(uint8* data, size_t datasize, const WildcardPattern & writepattern) void Pattern::Write(uint8* data, size_t datasize, const WildcardPattern & writepattern)
{ {
if (!writepattern.size()) if(!writepattern.size())
return; return;
auto writepatternsize = writepattern.size(); auto writepatternsize = writepattern.size();
if (writepatternsize > datasize) if(writepatternsize > datasize)
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 n1 = (*byte >> 4) & 0xF;
unsigned char n2 = *byte & 0xF; unsigned char n2 = *byte & 0xF;
if (!pbyte.nibble[0].wildcard) if(!pbyte.nibble[0].wildcard)
n1 = pbyte.nibble[0].data; n1 = pbyte.nibble[0].data;
if (!pbyte.nibble[1].wildcard) if(!pbyte.nibble[1].wildcard)
n2 = pbyte.nibble[1].data; n2 = pbyte.nibble[1].data;
*byte = ((n1 << 4) & 0xF0) | (n2 & 0xF); *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)); WriteByte(&data[i], writepattern.at(i));
} }
bool Pattern::SearchAndReplace(uint8* data, size_t datasize, const WildcardPattern & searchpattern, const WildcardPattern & replacepattern) bool Pattern::SearchAndReplace(uint8* data, size_t datasize, const WildcardPattern & searchpattern, const WildcardPattern & replacepattern)
{ {
auto found = Find(data, datasize, searchpattern); auto found = Find(data, datasize, searchpattern);
if (found == -1) if(found == -1)
return false; return false;
Write(data + found, datasize - found, replacepattern); Write(data + found, datasize - found, replacepattern);
return true; return true;

View File

@ -10,10 +10,10 @@ namespace GleeBug
public: public:
explicit Section(uint16 index, uint32 alignment, Region<IMAGE_SECTION_HEADER> & headers, Region<uint8> beforeData, Region<uint8> data) explicit Section(uint16 index, uint32 alignment, Region<IMAGE_SECTION_HEADER> & headers, Region<uint8> beforeData, Region<uint8> data)
: mIndex(index), : mIndex(index),
mAlignment(alignment), mAlignment(alignment),
mHeaders(headers), mHeaders(headers),
mBeforeData(beforeData), mBeforeData(beforeData),
mData(data) mData(data)
{ {
} }

View File

@ -49,24 +49,24 @@ namespace GleeBug
//read the DOS header //read the DOS header
mDosHeader = readRegion<IMAGE_DOS_HEADER>(); mDosHeader = readRegion<IMAGE_DOS_HEADER>();
if (!mDosHeader) if(!mDosHeader)
return ErrorDosHeaderRead; return ErrorDosHeaderRead;
//verify the DOS header //verify the DOS header
if (mDosHeader->e_magic != IMAGE_DOS_SIGNATURE) if(mDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
return ErrorDosHeaderMagic; return ErrorDosHeaderMagic;
//get the NT headers offset //get the NT headers offset
auto newOffset = mDosHeader->e_lfanew; auto newOffset = mDosHeader->e_lfanew;
//verify the new offset //verify the new offset
if (newOffset < 0 || uint32(newOffset) >= mFile.GetSize()) if(newOffset < 0 || uint32(newOffset) >= mFile.GetSize())
return ErrorDosHeaderNtHeaderOffset; return ErrorDosHeaderNtHeaderOffset;
//special case where DOS and PE header overlap (tinygui.exe) //special case where DOS and PE header overlap (tinygui.exe)
if (uint32(newOffset) < mOffset) if(uint32(newOffset) < mOffset)
{ {
if (!allowOverlap) if(!allowOverlap)
return ErrorDosHeaderNtHeaderOffsetOverlap; return ErrorDosHeaderNtHeaderOffsetOverlap;
mDosNtOverlap = true; mDosNtOverlap = true;
@ -80,38 +80,38 @@ namespace GleeBug
mAfterDosData = readRegion<uint8>(afterDosCount); mAfterDosData = readRegion<uint8>(afterDosCount);
} }
if (!mAfterDosData) if(!mAfterDosData)
return ErrorAfterDosHeaderData; return ErrorAfterDosHeaderData;
//read & verify the signature //read & verify the signature
auto signature = readRegion<DWORD>(); auto signature = readRegion<DWORD>();
if (!signature) if(!signature)
return ErrorNtSignatureRead; return ErrorNtSignatureRead;
if (*signature() != IMAGE_NT_SIGNATURE) if(*signature() != IMAGE_NT_SIGNATURE)
return ErrorNtSignatureMagic; return ErrorNtSignatureMagic;
//read the file header //read the file header
auto ifh = readRegion<IMAGE_FILE_HEADER>(); auto ifh = readRegion<IMAGE_FILE_HEADER>();
if (!ifh) if(!ifh)
return ErrorNtFileHeaderRead; return ErrorNtFileHeaderRead;
//read the optional header //read the optional header
uint32 realSizeOfIoh; uint32 realSizeOfIoh;
switch (ifh->Machine) switch(ifh->Machine)
{ {
case IMAGE_FILE_MACHINE_I386: case IMAGE_FILE_MACHINE_I386:
{ {
//read & verify the optional header //read & verify the optional header
realSizeOfIoh = uint32(sizeof(IMAGE_OPTIONAL_HEADER32)); realSizeOfIoh = uint32(sizeof(IMAGE_OPTIONAL_HEADER32));
auto ioh = readRegion<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; return ErrorNtOptionalHeaderRead;
if (ioh->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) if(ioh->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
return ErrorNtOptionalHeaderMagic; return ErrorNtOptionalHeaderMagic;
//construct & verify the NT headers region //construct & verify the NT headers region
mNtHeaders32 = Region<IMAGE_NT_HEADERS32>(&mData, signature.Offset()); mNtHeaders32 = Region<IMAGE_NT_HEADERS32>(&mData, signature.Offset());
if (!mNtHeaders32) if(!mNtHeaders32)
return ErrorNtHeadersRegionSize; return ErrorNtHeadersRegionSize;
} }
break; break;
@ -123,14 +123,14 @@ namespace GleeBug
//read & verify the optional header //read & verify the optional header
realSizeOfIoh = uint32(sizeof(IMAGE_OPTIONAL_HEADER64)); realSizeOfIoh = uint32(sizeof(IMAGE_OPTIONAL_HEADER64));
auto ioh = readRegion<IMAGE_OPTIONAL_HEADER64>(); auto ioh = readRegion<IMAGE_OPTIONAL_HEADER64>();
if (!ioh) if(!ioh)
return ErrorNtOptionalHeaderRead; return ErrorNtOptionalHeaderRead;
if (ioh->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) if(ioh->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
return ErrorNtOptionalHeaderMagic; return ErrorNtOptionalHeaderMagic;
//construct & verify the NT headers region //construct & verify the NT headers region
mNtHeaders64 = Region<IMAGE_NT_HEADERS64>(&mData, signature.Offset()); mNtHeaders64 = Region<IMAGE_NT_HEADERS64>(&mData, signature.Offset());
if (!mNtHeaders64) if(!mNtHeaders64)
return ErrorNtHeadersRegionSize; return ErrorNtHeadersRegionSize;
} }
break; break;
@ -139,11 +139,11 @@ namespace GleeBug
{ {
//try the best possible effort (corkami's d_resource.dll) //try the best possible effort (corkami's d_resource.dll)
auto ioh = readRegion<uint8>(ifh->SizeOfOptionalHeader); auto ioh = readRegion<uint8>(ifh->SizeOfOptionalHeader);
if (!ioh) if(!ioh)
return ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead; return ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead;
mNtHeaders32 = Region<IMAGE_NT_HEADERS32>(&mData, signature.Offset()); mNtHeaders32 = Region<IMAGE_NT_HEADERS32>(&mData, signature.Offset());
if (!mNtHeaders32) if(!mNtHeaders32)
return ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize; return ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize;
return ErrorNtFileHeaderUnsupportedMachine; return ErrorNtFileHeaderUnsupportedMachine;
@ -154,23 +154,23 @@ namespace GleeBug
//check the SizeOfOptionalHeader field //check the SizeOfOptionalHeader field
auto sizeOfIoh = ifh->SizeOfOptionalHeader; 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; return ErrorNtFileHeaderSizeOfOptionalHeaderOverlap;
//read data after the optional header (TODO: check if this is even possible) //read data after the optional header (TODO: check if this is even possible)
uint32 afterOptionalSize = realSizeOfIoh < sizeOfIoh ? sizeOfIoh - realSizeOfIoh : 0; uint32 afterOptionalSize = realSizeOfIoh < sizeOfIoh ? sizeOfIoh - realSizeOfIoh : 0;
mAfterOptionalData = readRegion<uint8>(afterOptionalSize); mAfterOptionalData = readRegion<uint8>(afterOptionalSize);
if (!mAfterOptionalData) if(!mAfterOptionalData)
return ErrorAfterOptionalHeaderDataRead; return ErrorAfterOptionalHeaderDataRead;
//read the section headers //read the section headers
mSectionHeaders = readRegion<IMAGE_SECTION_HEADER>(numberOfSections); mSectionHeaders = readRegion<IMAGE_SECTION_HEADER>(numberOfSections);
if (!mSectionHeaders) if(!mSectionHeaders)
return ErrorSectionHeadersRead; return ErrorSectionHeadersRead;
//parse the sections //parse the sections
auto sectionsError = parseSections(numberOfSections); auto sectionsError = parseSections(numberOfSections);
if (sectionsError != ErrorOk) if(sectionsError != ErrorOk)
return sectionsError; return sectionsError;
//TODO: parse data directories //TODO: parse data directories
@ -179,13 +179,13 @@ namespace GleeBug
uint32 Pe::ConvertOffsetToRva(uint32 offset) 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; return offset;
const auto found = mOffsetSectionMap.find(Range(offset, offset)); const auto found = mOffsetSectionMap.find(Range(offset, offset));
if (found == mOffsetSectionMap.end()) if(found == mOffsetSectionMap.end())
return INVALID_VALUE; return INVALID_VALUE;
auto index = found->second; auto index = found->second;
if (index == HeaderSection) if(index == HeaderSection)
return offset; return offset;
const auto & section = mSections[index]; const auto & section = mSections[index];
offset -= uint32(found->first.first); //adjust the offset to be relative to the offset range in the map 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) 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; return rva;
const auto found = mRvaSectionMap.find(Range(rva, rva)); const auto found = mRvaSectionMap.find(Range(rva, rva));
if (found == mRvaSectionMap.end()) if(found == mRvaSectionMap.end())
return INVALID_VALUE; return INVALID_VALUE;
auto index = found->second; auto index = found->second;
if (index == HeaderSection) if(index == HeaderSection)
return rva; return rva;
const auto & section = mSections[index]; const auto & section = mSections[index];
rva -= uint32(found->first.first); //adjust the rva to be relative to the rva range in the map 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) Pe::Error Pe::parseSections(uint16 count, uint32 alignment)
{ {
if (!count) if(!count)
return ErrorOk; return ErrorOk;
auto sectionHeaders = GetSectionHeaders(); auto sectionHeaders = GetSectionHeaders();
@ -225,7 +225,7 @@ namespace GleeBug
//sort sections on raw address to prevent read errors and have a contiguous buffer //sort sections on raw address to prevent read errors and have a contiguous buffer
std::vector<SectionInfo> sortedHeaders; std::vector<SectionInfo> sortedHeaders;
sortedHeaders.reserve(count); sortedHeaders.reserve(count);
for (uint16 i = 0; i < count; i++) for(uint16 i = 0; i < count; i++)
sortedHeaders.push_back(SectionInfo{ i, sectionHeaders[i] }); sortedHeaders.push_back(SectionInfo{ i, sectionHeaders[i] });
std::sort(sortedHeaders.begin(), sortedHeaders.end(), [](const SectionInfo & a, const SectionInfo & b) 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 //add the sections to the mSections vector
mSections.reserve(count); mSections.reserve(count);
for (uint16 i = 0; i < count; i++) for(uint16 i = 0; i < count; i++)
{ {
const auto & section = sortedHeaders[i]; const auto & section = sortedHeaders[i];
mSections.push_back(Section(i, alignment, mSectionHeaders, section.beforeData, section.data)); mSections.push_back(Section(i, alignment, mSectionHeaders, section.beforeData, section.data));
} }
//create rva/offset -> section maps //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]; const auto & section = mSections[0];
mOffsetSectionMap.insert({ Range(0, section.GetHeader().PointerToRawData - 1), HeaderSection }); mOffsetSectionMap.insert({ Range(0, section.GetHeader().PointerToRawData - 1), HeaderSection });
@ -287,7 +287,7 @@ namespace GleeBug
else //TODO: handle file without sections else //TODO: handle file without sections
{ {
} }
for (const auto & section : mSections) for(const auto & section : mSections)
{ {
//offset -> section index //offset -> section index
auto offset = section.GetHeader().PointerToRawData; auto offset = section.GetHeader().PointerToRawData;
@ -308,11 +308,11 @@ namespace GleeBug
uint32 Pe::readData(uint32 size) uint32 Pe::readData(uint32 size)
{ {
if (!size) if(!size)
return mOffset; return mOffset;
std::vector<uint8> temp(size); std::vector<uint8> temp(size);
if (!mFile.Read(mOffset, temp.data(), size)) if(!mFile.Read(mOffset, temp.data(), size))
return INVALID_VALUE; return INVALID_VALUE;
auto result = mOffset; auto result = mOffset;

View File

@ -29,8 +29,8 @@ namespace GleeBug
*/ */
explicit Region(std::vector<uint8>* data, uint32 offset, uint32 count = 1) explicit Region(std::vector<uint8>* data, uint32 offset, uint32 count = 1)
: mData(data), : mData(data),
mOffset(offset), mOffset(offset),
mCount(count) mCount(count)
{ {
} }
@ -48,7 +48,7 @@ namespace GleeBug
*/ */
T* Data() const T* Data() const
{ {
if (!Valid()) if(!Valid())
return nullptr; return nullptr;
return (T*)(mData->data() + mOffset); return (T*)(mData->data() + mOffset);
} }
@ -83,9 +83,9 @@ namespace GleeBug
bool Valid() const bool Valid() const
{ {
return mOffset != INVALID_VALUE && return mOffset != INVALID_VALUE &&
mCount != INVALID_VALUE && mCount != INVALID_VALUE &&
mData && mData->data() && mData && mData->data() &&
mOffset + mCount * sizeof(T) <= mData->size(); mOffset + mCount * sizeof(T) <= mData->size();
} }
/** /**
@ -107,7 +107,7 @@ namespace GleeBug
/** /**
\brief Returns Data(). \brief Returns Data().
*/ */
T* operator ()() const T* operator()() const
{ {
return Data(); return Data();
} }

View File

@ -12,7 +12,7 @@ protected:
void cbMemoryBreakpoint2(const BreakpointInfo & info) void cbMemoryBreakpoint2(const BreakpointInfo & info)
{ {
printf("Reached memory breakpoint#2! GIP: 0x%p\n", printf("Reached memory breakpoint#2! GIP: 0x%p\n",
(void*)Registers(mThread->hThread).Gip()); (void*)Registers(mThread->hThread).Gip());
} }
void cbMemoryBreakpoint(const BreakpointInfo & info) void cbMemoryBreakpoint(const BreakpointInfo & info)
@ -22,11 +22,11 @@ protected:
Registers registers(mThread->hThread); Registers registers(mThread->hThread);
printf("Reached memory breakpoint! GIP: 0x%p\n", printf("Reached memory breakpoint! GIP: 0x%p\n",
(void*)registers.Gip()); (void*)registers.Gip());
mProcess->MemReadUnsafe(registers.Gip(), dataToExec, 4); mProcess->MemReadUnsafe(registers.Gip(), dataToExec, 4);
printf("\n What are my bytes? I am so lost.. Dump: "); 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]); printf("%02X ", dataToExec[i]);
} }
@ -35,7 +35,7 @@ protected:
memcpy(dataToExec, tmp, 4); memcpy(dataToExec, tmp, 4);
mProcess->MemReadUnsafe(registers.Gip(), dataToExec, 4); mProcess->MemReadUnsafe(registers.Gip(), dataToExec, 4);
printf("\n What are my bytes? I am so lost.. Dump: "); 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]); printf("%02X ", dataToExec[i]);
} }
@ -43,7 +43,7 @@ protected:
memcpy(dataToExec, tmp, 4); memcpy(dataToExec, tmp, 4);
mProcess->MemReadUnsafe(registers.Gip(), dataToExec, 4); mProcess->MemReadUnsafe(registers.Gip(), dataToExec, 4);
printf("\n What are my bytes? I am so lost.. Dump: "); 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]); printf("%02X ", dataToExec[i]);
} }
@ -53,14 +53,14 @@ protected:
{ {
Registers registers(mThread->hThread); Registers registers(mThread->hThread);
printf("Reached entry breakpoint! GIP: 0x%p\n", printf("Reached entry breakpoint! GIP: 0x%p\n",
(void*)registers.Gip()); (void*)registers.Gip());
#ifdef _WIN64 #ifdef _WIN64
auto addr = registers.Rbx(); auto addr = registers.Rbx();
#else #else
auto addr = registers.Esi(); auto addr = registers.Esi();
#endif //_WIN64 #endif //_WIN64
printf("Addr: 0x%p\n", (void*)addr); 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!"); puts("Memory breakpoint set!");
else else
puts("Failed to set memory breakpoint..."); puts("Failed to set memory breakpoint...");
@ -82,8 +82,8 @@ protected:
{ {
Registers registers(mThread->hThread); Registers registers(mThread->hThread);
printf("Reached entry hardware breakpoint! GIP: 0x%p\n", printf("Reached entry hardware breakpoint! GIP: 0x%p\n",
(void*)registers.Gip()); (void*)registers.Gip());
if (mProcess->DeleteHardwareBreakpoint(info.address)) if(mProcess->DeleteHardwareBreakpoint(info.address))
printf("Entry hardware breakpoint deleted!\n"); printf("Entry hardware breakpoint deleted!\n");
else else
printf("Failed to delete entry hardware breakpoint...\n"); printf("Failed to delete entry hardware breakpoint...\n");
@ -91,7 +91,7 @@ protected:
{ {
Registers registers(mThread->hThread); Registers registers(mThread->hThread);
printf("Step after entry hardware breakpoint! GIP: 0x%p\n", 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); Registers registers(mThread->hThread);
printf("Reached step after system breakpoint, GIP: 0x%p!\n", 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 void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const Process & process) override
{ {
ptr entry = ptr(createProcess.lpStartAddress); ptr entry = ptr(createProcess.lpStartAddress);
printf("Process %d created with entry 0x%p\n", printf("Process %d created with entry 0x%p\n",
mDebugEvent.dwProcessId, mDebugEvent.dwProcessId,
(void*)entry); (void*)entry);
/*HardwareSlot slot; /*HardwareSlot slot;
if (mProcess->GetFreeHardwareBreakpointSlot(slot)) if (mProcess->GetFreeHardwareBreakpointSlot(slot))
{ {
@ -133,12 +133,12 @@ protected:
ptr start = entry - 2; ptr start = entry - 2;
printf("unsafe: "); printf("unsafe: ");
mProcess->MemReadUnsafe(start, test, sizeof(test)); 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]); printf("%02X ", test[i]);
puts(""); puts("");
mProcess->MemReadSafe(start, test, sizeof(test)); mProcess->MemReadSafe(start, test, sizeof(test));
printf(" safe: "); printf(" safe: ");
for (int i = 0; i < sizeof(test); i++) for(int i = 0; i < sizeof(test); i++)
printf("%02X ", test[i]); printf("%02X ", test[i]);
puts(""); puts("");
} }
@ -146,96 +146,96 @@ protected:
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const Process & process) override void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const Process & process) override
{ {
printf("Process %u terminated with exit code 0x%08X\n", printf("Process %u terminated with exit code 0x%08X\n",
mDebugEvent.dwProcessId, mDebugEvent.dwProcessId,
exitProcess.dwExitCode); exitProcess.dwExitCode);
} }
void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const Thread & thread) override void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const Thread & thread) override
{ {
printf("Thread %u created with entry 0x%p\n", printf("Thread %u created with entry 0x%p\n",
mDebugEvent.dwThreadId, mDebugEvent.dwThreadId,
createThread.lpStartAddress); createThread.lpStartAddress);
} }
void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const Thread & thread) override void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const Thread & thread) override
{ {
printf("Thread %u terminated with exit code 0x%08X\n", printf("Thread %u terminated with exit code 0x%08X\n",
mDebugEvent.dwThreadId, mDebugEvent.dwThreadId,
exitThread.dwExitCode); exitThread.dwExitCode);
} }
void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) override void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) override
{ {
printf("DLL loaded at 0x%p\n", printf("DLL loaded at 0x%p\n",
loadDll.lpBaseOfDll); loadDll.lpBaseOfDll);
} }
void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll) override void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll) override
{ {
printf("DLL 0x%p unloaded\n", printf("DLL 0x%p unloaded\n",
unloadDll.lpBaseOfDll); unloadDll.lpBaseOfDll);
} }
void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) override void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) override
{ {
const char* exceptionType = exceptionInfo.dwFirstChance ? "First Chance" : "Second Chance"; const char* exceptionType = exceptionInfo.dwFirstChance ? "First Chance" : "Second Chance";
printf("%s exception with code 0x%08X at 0x%p\n", printf("%s exception with code 0x%08X at 0x%p\n",
exceptionType, exceptionType,
exceptionInfo.ExceptionRecord.ExceptionCode, exceptionInfo.ExceptionRecord.ExceptionCode,
exceptionInfo.ExceptionRecord.ExceptionAddress); exceptionInfo.ExceptionRecord.ExceptionAddress);
for (DWORD i = 0; i < exceptionInfo.ExceptionRecord.NumberParameters; i++) for(DWORD i = 0; i < exceptionInfo.ExceptionRecord.NumberParameters; i++)
printf(" ExceptionInformation[%d] = 0x%p\n", i, (void*)exceptionInfo.ExceptionRecord.ExceptionInformation[i]); printf(" ExceptionInformation[%d] = 0x%p\n", i, (void*)exceptionInfo.ExceptionRecord.ExceptionInformation[i]);
} }
void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) override void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) override
{ {
printf("Debug string at 0x%p with length %d\n", printf("Debug string at 0x%p with length %d\n",
debugString.lpDebugStringData, debugString.lpDebugStringData,
debugString.nDebugStringLength); debugString.nDebugStringLength);
} }
void cbRipEvent(const RIP_INFO & rip) override void cbRipEvent(const RIP_INFO & rip) override
{ {
printf("RIP event type 0x%X, error 0x%X", printf("RIP event type 0x%X, error 0x%X",
rip.dwType, rip.dwType,
rip.dwError); rip.dwError);
} }
void cbAttachBreakpoint() override void cbAttachBreakpoint() override
{ {
Registers registers(mThread->hThread); Registers registers(mThread->hThread);
printf("Attach breakpoint reached, GIP: 0x%p\n", printf("Attach breakpoint reached, GIP: 0x%p\n",
(void*)registers.Gip()); (void*)registers.Gip());
} }
void cbSystemBreakpoint() override void cbSystemBreakpoint() override
{ {
Registers registers(mThread->hThread); Registers registers(mThread->hThread);
printf("System breakpoint reached, GIP: 0x%p\n", printf("System breakpoint reached, GIP: 0x%p\n",
(void*)registers.Gip()); (void*)registers.Gip());
mThread->StepInto(this, &MyDebugger::cbStepSystem); mThread->StepInto(this, &MyDebugger::cbStepSystem);
} }
void cbInternalError(const std::string & error) override void cbInternalError(const std::string & error) override
{ {
printf("Internal Error: %s\n", printf("Internal Error: %s\n",
error.c_str()); error.c_str());
} }
void cbBreakpoint(const BreakpointInfo & info) override void cbBreakpoint(const BreakpointInfo & info) override
{ {
printf("Breakpoint on 0x%p!\n", printf("Breakpoint on 0x%p!\n",
(void*)info.address); (void*)info.address);
} }
void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) override void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) override
{ {
Registers registers(mThread->hThread); Registers registers(mThread->hThread);
printf("Unhandled exception (%s) 0x%08X on 0x%p, GIP: 0x%p\n", printf("Unhandled exception (%s) 0x%08X on 0x%p, GIP: 0x%p\n",
firstChance ? "first chance" : "second chance", firstChance ? "first chance" : "second chance",
exceptionRecord.ExceptionCode, exceptionRecord.ExceptionCode,
exceptionRecord.ExceptionAddress, exceptionRecord.ExceptionAddress,
(void*)registers.Gip()); (void*)registers.Gip());
} }
}; };

View File

@ -14,7 +14,7 @@ static void testDebugger()
wchar_t szCommandLine[256] = L""; wchar_t szCommandLine[256] = L"";
wchar_t szCurrentDir[256] = L"c:\\"; wchar_t szCurrentDir[256] = L"c:\\";
MyDebugger dbg; MyDebugger dbg;
if (dbg.Init(szFilePath, szCommandLine, szCurrentDir)) if(dbg.Init(szFilePath, szCommandLine, szCurrentDir))
{ {
puts("Debugger::Init success!"); puts("Debugger::Init success!");
dbg.Start(); dbg.Start();
@ -30,12 +30,12 @@ template<typename T>
static void printRegion(const char* str, Region<T> region, bool newline = true) 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)", printf("\n%s (offset: 0x%X, size: 0x%X, v: %s, e: %s)",
str, str,
region.Offset(), region.Offset(),
region.Size(), region.Size(),
region.Valid() ? "true" : "false", region.Valid() ? "true" : "false",
region.Empty() ? "true" : "false"); region.Empty() ? "true" : "false");
if (newline) if(newline)
puts(""); puts("");
} }
@ -65,19 +65,19 @@ static bool testPeFile(const wchar_t* szFileName, bool dumpData = true)
using namespace GleeBug; using namespace GleeBug;
auto result = false; auto result = false;
File diskFile(szFileName, File::ReadOnly); File diskFile(szFileName, File::ReadOnly);
if (diskFile.Open()) if(diskFile.Open())
{ {
auto diskSize = diskFile.GetSize(); auto diskSize = diskFile.GetSize();
std::vector<uint8> diskData(diskSize); std::vector<uint8> diskData(diskSize);
if (diskFile.Read(0, diskData.data(), diskSize)) if(diskFile.Read(0, diskData.data(), diskSize))
{ {
BufferFile file(diskData.data(), diskSize); BufferFile file(diskData.data(), diskSize);
Pe pe(file); Pe pe(file);
auto parseError = pe.Parse(true); auto parseError = pe.Parse(true);
if (parseError == Pe::ErrorOk) if(parseError == Pe::ErrorOk)
{ {
result = true; result = true;
if (!dumpData) if(!dumpData)
return result; return result;
auto idh = pe.GetDosHeader(); auto idh = pe.GetDosHeader();
printRegion("DOS Header:", idh); printRegion("DOS Header:", idh);
@ -87,7 +87,7 @@ static bool testPeFile(const wchar_t* szFileName, bool dumpData = true)
auto afterDosData = pe.GetAfterDosData(); auto afterDosData = pe.GetAfterDosData();
printRegion("After DOS Data", afterDosData); printRegion("After DOS Data", afterDosData);
if (pe.IsPe64()) if(pe.IsPe64())
printNtHeaders(pe.GetNtHeaders64()); printNtHeaders(pe.GetNtHeaders64());
else else
printNtHeaders(pe.GetNtHeaders32()); printNtHeaders(pe.GetNtHeaders32());
@ -100,9 +100,9 @@ static bool testPeFile(const wchar_t* szFileName, bool dumpData = true)
auto afterSectionHeadersData = pe.GetAfterSectionHeadersData(); auto afterSectionHeadersData = pe.GetAfterSectionHeadersData();
printRegion("After Section Headers Data", afterSectionHeadersData); printRegion("After Section Headers Data", afterSectionHeadersData);
auto sections = pe.GetSections(); auto sections = pe.GetSections();
for (const auto & section : sections) for(const auto & section : sections)
{ {
if (section.GetIndex()) if(section.GetIndex())
puts(""); puts("");
printf(" Section %d:\n", section.GetIndex()); printf(" Section %d:\n", section.GetIndex());
auto cur = section.GetHeader(); auto cur = section.GetHeader();
@ -118,13 +118,13 @@ static bool testPeFile(const wchar_t* szFileName, bool dumpData = true)
} }
printf("\nOffset -> Section:\n"); 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(" %08llX:%08llX -> %d\n", range.first.first, range.first.second, range.second);
} }
printf("\nRva -> Section:\n"); 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); printf(" %08llX:%08llX -> %d\n", range.first.first, range.first.second, range.second);
} }
@ -145,11 +145,11 @@ static void testCorkami()
#include "PeTests.h" #include "PeTests.h"
wchar_t szBasePath[MAX_PATH] = L"c:\\!exclude\\pe\\bin\\"; wchar_t szBasePath[MAX_PATH] = L"c:\\!exclude\\pe\\bin\\";
int okCount = 0; int okCount = 0;
for (auto i = 0; i < _countof(peTestFiles); i++) for(auto i = 0; i < _countof(peTestFiles); i++)
{ {
std::wstring fileName(szBasePath); std::wstring fileName(szBasePath);
fileName += peTestFiles[i]; fileName += peTestFiles[i];
if (testPeFile(fileName.c_str(), false)) if(testPeFile(fileName.c_str(), false))
okCount++; okCount++;
else else
{ {

View File

@ -108,7 +108,8 @@ public:
dwMainThreadId = te.th32ThreadID; dwMainThreadId = te.th32ThreadID;
} }
te.dwSize = sizeof(te); te.dwSize = sizeof(te);
} while(Thread32Next(h, &te)); }
while(Thread32Next(h, &te));
} }
CloseHandle(h); CloseHandle(h);
} }
@ -244,11 +245,11 @@ public:
if(!lpNumberOfBytesRead) if(!lpNumberOfBytesRead)
lpNumberOfBytesRead = &s; lpNumberOfBytesRead = &s;
auto x = !!ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead); auto x = !!ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead);
if (!x && nSize <= 0x1000) if(!x && nSize <= 0x1000)
{ {
NtSuspendProcess(hProcess); NtSuspendProcess(hProcess);
DWORD oldProtect = 0; 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); x = !!ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead);
VirtualProtectEx(hProcess, lpBaseAddress, 0x1000, oldProtect, &oldProtect); VirtualProtectEx(hProcess, lpBaseAddress, 0x1000, oldProtect, &oldProtect);
@ -275,7 +276,7 @@ public:
//Engine //Engine
bool EngineCheckStructAlignment(DWORD StructureType, ULONG_PTR StructureSize) const 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 StructureSize == sizeof(TITAN_ENGINE_CONTEXT_t);
return false; return false;
} }
@ -292,7 +293,7 @@ public:
void SetCustomHandler(DWORD ExceptionId, PVOID CallBack) void SetCustomHandler(DWORD ExceptionId, PVOID CallBack)
{ {
switch (ExceptionId) switch(ExceptionId)
{ {
case UE_CH_CREATEPROCESS: case UE_CH_CREATEPROCESS:
mCbCREATEPROCESS = CUSTOMHANDLER(CallBack); mCbCREATEPROCESS = CUSTOMHANDLER(CallBack);
@ -386,11 +387,11 @@ public:
HANDLE TitanOpenProcess(DWORD dwDesiredAccess, bool bInheritHandle, DWORD dwProcessId) HANDLE TitanOpenProcess(DWORD dwDesiredAccess, bool bInheritHandle, DWORD dwProcessId)
{ {
if (mSetDebugPrivilege) if(mSetDebugPrivilege)
setDebugPrivilege(GetCurrentProcess(), true); setDebugPrivilege(GetCurrentProcess(), true);
HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
DWORD dwLastError = GetLastError(); DWORD dwLastError = GetLastError();
if (mSetDebugPrivilege) if(mSetDebugPrivilege)
setDebugPrivilege(GetCurrentProcess(), false); setDebugPrivilege(GetCurrentProcess(), false);
SetLastError(dwLastError); SetLastError(dwLastError);
return hProcess; return hProcess;
@ -398,11 +399,11 @@ public:
HANDLE TitanOpenThread(DWORD dwDesiredAccess, bool bInheritHandle, DWORD dwThreadId) HANDLE TitanOpenThread(DWORD dwDesiredAccess, bool bInheritHandle, DWORD dwThreadId)
{ {
if (mSetDebugPrivilege) if(mSetDebugPrivilege)
setDebugPrivilege(GetCurrentProcess(), true); setDebugPrivilege(GetCurrentProcess(), true);
HANDLE hThread = OpenThread(dwDesiredAccess, bInheritHandle, dwThreadId); HANDLE hThread = OpenThread(dwDesiredAccess, bInheritHandle, dwThreadId);
DWORD dwLastError = GetLastError(); DWORD dwLastError = GetLastError();
if (mSetDebugPrivilege) if(mSetDebugPrivilege)
setDebugPrivilege(GetCurrentProcess(), false); setDebugPrivilege(GetCurrentProcess(), false);
SetLastError(dwLastError); SetLastError(dwLastError);
return hThread; 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) 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>; 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; __debugbreak(); //return false;
*FileHandle = file->hFile; *FileHandle = file->hFile;
*LoadedSize = file->size; *LoadedSize = file->size;
@ -486,7 +487,7 @@ public:
mappedPe.file = std::move(file); mappedPe.file = std::move(file);
mappedPe.buffer = new BufferFile(mappedPe.file->data, mappedPe.file->size); mappedPe.buffer = new BufferFile(mappedPe.file->data, mappedPe.file->size);
mappedPe.pe = new Pe(*mappedPe.buffer); mappedPe.pe = new Pe(*mappedPe.buffer);
if (mappedPe.pe->Parse(true) != Pe::ErrorOk) if(mappedPe.pe->Parse(true) != Pe::ErrorOk)
__debugbreak(); __debugbreak();
mappedFiles.insert({ *FileMapVA, mappedPe }); mappedFiles.insert({ *FileMapVA, mappedPe });
return true; return true;
@ -495,7 +496,7 @@ public:
bool StaticFileUnloadW(const wchar_t* szFileName, bool CommitChanges, HANDLE FileHandle, DWORD LoadedSize, HANDLE FileMap, ULONG_PTR FileMapVA) bool StaticFileUnloadW(const wchar_t* szFileName, bool CommitChanges, HANDLE FileHandle, DWORD LoadedSize, HANDLE FileMap, ULONG_PTR FileMapVA)
{ {
auto found = mappedFiles.find(FileMapVA); auto found = mappedFiles.find(FileMapVA);
if (found == mappedFiles.end()) if(found == mappedFiles.end())
__debugbreak(); //return false; __debugbreak(); //return false;
delete found->second.pe; delete found->second.pe;
delete found->second.buffer; delete found->second.buffer;
@ -517,21 +518,21 @@ public:
) )
{ {
auto found = mappedFiles.find(FileMapVA); auto found = mappedFiles.find(FileMapVA);
if (found == mappedFiles.end()) if(found == mappedFiles.end())
__debugbreak(); //return 0; __debugbreak(); //return 0;
if (!found->second.pe->IsValidPe()) if(!found->second.pe->IsValidPe())
__debugbreak(); //return 0; __debugbreak(); //return 0;
if (AddressToConvert < FileMapVA) if(AddressToConvert < FileMapVA)
__debugbreak(); __debugbreak();
// convert: FileOffset -> VA // convert: FileOffset -> VA
auto offset = found->second.pe->ConvertOffsetToRva( auto offset = found->second.pe->ConvertOffsetToRva(
uint32( AddressToConvert - FileMapVA ) uint32(AddressToConvert - FileMapVA)
); );
if (offset == INVALID_VALUE) if(offset == INVALID_VALUE)
return 0; return 0;
else else
return ReturnType ? FileMapVA + offset : offset; return ReturnType ? FileMapVA + offset : offset;
@ -551,8 +552,8 @@ public:
) )
{ {
return ConvertVAtoFileOffsetEx( return ConvertVAtoFileOffsetEx(
FileMapVA ,0 ,0 , FileMapVA, 0, 0,
AddressToConvert, false, ReturnType ); AddressToConvert, false, ReturnType);
} }
//// ////
@ -572,23 +573,23 @@ public:
) )
{ {
auto found = mappedFiles.find(FileMapVA); auto found = mappedFiles.find(FileMapVA);
if (found == mappedFiles.end()) if(found == mappedFiles.end())
__debugbreak(); //return 0; __debugbreak(); //return 0;
if (!found->second.pe->IsValidPe()) if(!found->second.pe->IsValidPe())
__debugbreak(); //return 0; __debugbreak(); //return 0;
// Convert to RVA if needed // Convert to RVA if needed
auto RVA_ToConvert = AddressIsRVA ? auto RVA_ToConvert = AddressIsRVA ?
AddressToConvert : AddressToConvert :
AddressToConvert - ImageBase; AddressToConvert - ImageBase;
// convert: VA -> FileOffset // convert: VA -> FileOffset
auto offset = found->second.pe->ConvertRvaToOffset( auto offset = found->second.pe->ConvertRvaToOffset(
uint32( RVA_ToConvert ) uint32(RVA_ToConvert)
); );
if (offset == INVALID_VALUE) if(offset == INVALID_VALUE)
return 0; return 0;
else else
return ReturnType ? FileMapVA + offset : offset; return ReturnType ? FileMapVA + offset : offset;
@ -597,7 +598,7 @@ public:
template<typename T> template<typename T>
ULONG_PTR GetPE32DataW_impl(const Region<T> & headers, DWORD WhichSection, DWORD WhichData, const std::vector<Section> & sections) 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: case UE_PE_OFFSET:
return headers.Offset(); return headers.Offset();
@ -652,14 +653,14 @@ public:
ULONG_PTR GetPE32DataFromMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData) ULONG_PTR GetPE32DataFromMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData)
{ {
auto found = mappedFiles.find(FileMapVA); auto found = mappedFiles.find(FileMapVA);
if (found == mappedFiles.end()) if(found == mappedFiles.end())
__debugbreak(); //return 0; __debugbreak(); //return 0;
if (!found->second.pe->IsValidPe()) if(!found->second.pe->IsValidPe())
__debugbreak(); //return 0; __debugbreak(); //return 0;
auto sections = found->second.pe->GetSections(); auto sections = found->second.pe->GetSections();
return found->second.pe->IsPe64() return found->second.pe->IsPe64()
? GetPE32DataW_impl(found->second.pe->GetNtHeaders64(), WhichSection, WhichData, sections) ? GetPE32DataW_impl(found->second.pe->GetNtHeaders64(), WhichSection, WhichData, sections)
: GetPE32DataW_impl(found->second.pe->GetNtHeaders32(), WhichSection, WhichData, sections); : GetPE32DataW_impl(found->second.pe->GetNtHeaders32(), WhichSection, WhichData, sections);
} }
ULONG_PTR GetPE32Data(const char* szFileName, DWORD WhichSection, DWORD WhichData) 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) ULONG_PTR GetPE32DataW(const wchar_t* szFileName, DWORD WhichSection, DWORD WhichData)
{ {
FileMap<unsigned char> file; FileMap<unsigned char> file;
if (!file.Map(szFileName)) if(!file.Map(szFileName))
__debugbreak(); //return 0; __debugbreak(); //return 0;
BufferFile buf(file.data, file.size); BufferFile buf(file.data, file.size);
Pe pe(buf); Pe pe(buf);
if (pe.Parse(true) != Pe::ErrorOk) if(pe.Parse(true) != Pe::ErrorOk)
__debugbreak(); //return 0; __debugbreak(); //return 0;
if (!pe.IsValidPe()) if(!pe.IsValidPe())
__debugbreak(); //return 0; __debugbreak(); //return 0;
auto sections = pe.GetSections(); auto sections = pe.GetSections();
return pe.IsPe64() return pe.IsPe64()
? GetPE32DataW_impl(pe.GetNtHeaders64(), WhichSection, WhichData, sections) ? GetPE32DataW_impl(pe.GetNtHeaders64(), WhichSection, WhichData, sections)
: GetPE32DataW_impl(pe.GetNtHeaders32(), WhichSection, WhichData, sections); : GetPE32DataW_impl(pe.GetNtHeaders32(), WhichSection, WhichData, sections);
} }
bool IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA) bool IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA)
@ -767,17 +768,17 @@ private: //functions
{ {
DWORD dwLastError; DWORD dwLastError;
HANDLE hToken = 0; HANDLE hToken = 0;
if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) if(!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{ {
dwLastError = GetLastError(); dwLastError = GetLastError();
if (hToken) if(hToken)
CloseHandle(hToken); CloseHandle(hToken);
return dwLastError; return dwLastError;
} }
TOKEN_PRIVILEGES tokenPrivileges; TOKEN_PRIVILEGES tokenPrivileges;
memset(&tokenPrivileges, 0, sizeof(TOKEN_PRIVILEGES)); memset(&tokenPrivileges, 0, sizeof(TOKEN_PRIVILEGES));
LUID luid; LUID luid;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
{ {
dwLastError = GetLastError(); dwLastError = GetLastError();
CloseHandle(hToken); CloseHandle(hToken);
@ -785,7 +786,7 @@ private: //functions
} }
tokenPrivileges.PrivilegeCount = 1; tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Privileges[0].Luid = luid; tokenPrivileges.Privileges[0].Luid = luid;
if (bEnablePrivilege) if(bEnablePrivilege)
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else else
tokenPrivileges.Privileges[0].Attributes = 0; tokenPrivileges.Privileges[0].Attributes = 0;

View File

@ -122,10 +122,10 @@ __declspec(dllexport) ULONG_PTR TITCALL ImporterGetRemoteAPIAddressEx(const char
static auto hModule = GetModuleHandleW(X64DBG_DLL); static auto hModule = GetModuleHandleW(X64DBG_DLL);
#undef X64DBG_DLL #undef X64DBG_DLL
if (hModule) if(hModule)
{ {
static auto DbgValFromString = (ULONG_PTR(*)(const char*))GetProcAddress(hModule, "DbgValFromString"); static auto DbgValFromString = (ULONG_PTR(*)(const char*))GetProcAddress(hModule, "DbgValFromString");
if (DbgValFromString) if(DbgValFromString)
{ {
char expr[1024] = ""; char expr[1024] = "";
_snprintf_s(expr, _TRUNCATE, "\"%s\":%s", szDLLName, szAPIName); _snprintf_s(expr, _TRUNCATE, "\"%s\":%s", szDLLName, szAPIName);
@ -293,7 +293,7 @@ BOOL WINAPI DllMain(
_In_ LPVOID lpvReserved _In_ LPVOID lpvReserved
) )
{ {
if (fdwReason == DLL_PROCESS_ATTACH) if(fdwReason == DLL_PROCESS_ATTACH)
emu.engineHandle = hinstDLL; emu.engineHandle = hinstDLL;
return TRUE; return TRUE;
} }

View File

@ -28,7 +28,7 @@ public:
PROCESS_INFORMATION* InitDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder) PROCESS_INFORMATION* InitDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder)
{ {
mCbATTACHBREAKPOINT = nullptr; mCbATTACHBREAKPOINT = nullptr;
if (!Init(szFileName, szCommandLine, szCurrentFolder)) if(!Init(szFileName, szCommandLine, szCurrentFolder))
return nullptr; return nullptr;
return &mMainProcess; 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 */) 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); wcscpy_s(szDebuggeeName, szFileName);
if (TryExtractDllLoader()) if(TryExtractDllLoader())
{ {
mCbATTACHBREAKPOINT = nullptr; mCbATTACHBREAKPOINT = nullptr;
if (!Init(szDebuggeeName, szCommandLine, szCurrentFolder, true, true)) if(!Init(szDebuggeeName, szCommandLine, szCurrentFolder, true, true))
return nullptr; return nullptr;
wchar_t szName[256] = L""; wchar_t szName[256] = L"";
swprintf(szName, 256, L"Local\\szLibraryName%X", mMainProcess.dwProcessId); swprintf(szName, 256, L"Local\\szLibraryName%X", mMainProcess.dwProcessId);
//TODO: close this once we actually see the DLL is loaded in the process //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); HANDLE DebugDLLFileMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 512 * sizeof(wchar_t), szName);
if (DebugDLLFileMapping) if(DebugDLLFileMapping)
{ {
const size_t filemapSize = 512; const size_t filemapSize = 512;
wchar_t* szLibraryPathMapping = (wchar_t*)MapViewOfFile(DebugDLLFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, filemapSize * sizeof(wchar_t)); 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); wcscpy_s(szLibraryPathMapping, filemapSize, szFileName);
UnmapViewOfFile(szLibraryPathMapping); UnmapViewOfFile(szLibraryPathMapping);
@ -98,7 +98,7 @@ public:
bool MemoryReadSafe(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) bool MemoryReadSafe(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead)
{ {
auto process = processFromHandle(hProcess); auto process = processFromHandle(hProcess);
if (!process) if(!process)
return false; return false;
return process->MemReadSafe(ptr(lpBaseAddress), lpBuffer, nSize, (ptr*)lpNumberOfBytesRead); 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) bool MemoryWriteSafe(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten)
{ {
auto process = processFromHandle(hProcess); auto process = processFromHandle(hProcess);
if (!process) if(!process)
return false; return false;
return process->MemWriteSafe(ptr(lpBaseAddress), lpBuffer, nSize, (ptr*)lpNumberOfBytesWritten); return process->MemWriteSafe(ptr(lpBaseAddress), lpBuffer, nSize, (ptr*)lpNumberOfBytesWritten);
} }
@ -114,11 +114,11 @@ public:
bool Fill(LPVOID MemoryStart, DWORD MemorySize, PBYTE FillByte) bool Fill(LPVOID MemoryStart, DWORD MemorySize, PBYTE FillByte)
{ {
//TODO: this is fucking inefficient //TODO: this is fucking inefficient
if (!mProcess) if(!mProcess)
return false; 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 false;
} }
return true; return true;
@ -127,7 +127,7 @@ public:
//Engine //Engine
bool EngineCheckStructAlignment(DWORD StructureType, ULONG_PTR StructureSize) const 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 StructureSize == sizeof(TITAN_ENGINE_CONTEXT_t);
return false; return false;
} }
@ -144,7 +144,7 @@ public:
void SetCustomHandler(DWORD ExceptionId, PVOID CallBack) void SetCustomHandler(DWORD ExceptionId, PVOID CallBack)
{ {
switch (ExceptionId) switch(ExceptionId)
{ {
case UE_CH_CREATEPROCESS: case UE_CH_CREATEPROCESS:
mCbCREATEPROCESS = CUSTOMHANDLER(CallBack); mCbCREATEPROCESS = CUSTOMHANDLER(CallBack);
@ -183,7 +183,7 @@ public:
void SetEngineVariable(DWORD VariableId, bool VariableSet) void SetEngineVariable(DWORD VariableId, bool VariableSet)
{ {
switch (VariableId) switch(VariableId)
{ {
case UE_ENGINE_SET_DEBUG_PRIVILEGE: case UE_ENGINE_SET_DEBUG_PRIVILEGE:
mSetDebugPrivilege = VariableSet; mSetDebugPrivilege = VariableSet;
@ -303,7 +303,7 @@ public:
ULONG_PTR GetDebuggedFileBaseAddress() ULONG_PTR GetDebuggedFileBaseAddress()
{ {
auto itr = mProcesses.find(mMainProcess.dwProcessId); auto itr = mProcesses.find(mMainProcess.dwProcessId);
if (itr != mProcesses.end()) if(itr != mProcesses.end())
return (ULONG_PTR)itr->second->createProcessInfo.lpBaseOfImage; return (ULONG_PTR)itr->second->createProcessInfo.lpBaseOfImage;
return 0; return 0;
} }
@ -311,14 +311,14 @@ public:
//Stepping //Stepping
void StepOver(LPVOID CallBack) void StepOver(LPVOID CallBack)
{ {
if (!mProcess || !CallBack) if(!mProcess || !CallBack)
return; return;
mProcess->StepOver(STEPCALLBACK(CallBack)); mProcess->StepOver(STEPCALLBACK(CallBack));
} }
void StepInto(LPVOID CallBack) void StepInto(LPVOID CallBack)
{ {
if (!mThread || !CallBack) if(!mThread || !CallBack)
return; return;
mThread->StepInto(STEPCALLBACK(CallBack)); mThread->StepInto(STEPCALLBACK(CallBack));
} }
@ -328,7 +328,7 @@ public:
ThreadSuspender(HANDLE hThread, bool running) ThreadSuspender(HANDLE hThread, bool running)
: hThread(running ? hThread : nullptr) : hThread(running ? hThread : nullptr)
{ {
if (this->hThread) if(this->hThread)
SuspendThread(this->hThread); SuspendThread(this->hThread);
} }
@ -337,7 +337,7 @@ public:
~ThreadSuspender() ~ThreadSuspender()
{ {
if (this->hThread) if(this->hThread)
ResumeThread(this->hThread); ResumeThread(this->hThread);
} }
@ -347,36 +347,36 @@ public:
//Registers //Registers
ULONG_PTR GetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister) ULONG_PTR GetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister)
{ {
if (!hActiveThread) if(!hActiveThread)
return 0; return 0;
ThreadSuspender suspender(hActiveThread, mIsRunning); ThreadSuspender suspender(hActiveThread, mIsRunning);
auto r = registerFromDword(IndexOfRegister); auto r = registerFromDword(IndexOfRegister);
if (r == Registers::R::Invalid) if(r == Registers::R::Invalid)
__debugbreak(); __debugbreak();
return Registers(hActiveThread).Get(r); return Registers(hActiveThread).Get(r);
} }
bool SetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister, ULONG_PTR NewRegisterValue) bool SetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister, ULONG_PTR NewRegisterValue)
{ {
if (!hActiveThread) if(!hActiveThread)
return 0; return 0;
ThreadSuspender suspender(hActiveThread, mIsRunning); ThreadSuspender suspender(hActiveThread, mIsRunning);
auto r = registerFromDword(IndexOfRegister); auto r = registerFromDword(IndexOfRegister);
if (r != Registers::R::Invalid) if(r != Registers::R::Invalid)
{ {
Registers(hActiveThread).Set(r, NewRegisterValue); Registers(hActiveThread).Set(r, NewRegisterValue);
return true; return true;
} }
TITAN_ENGINE_CONTEXT_t titcontext; TITAN_ENGINE_CONTEXT_t titcontext;
if (!_GetFullContextDataEx(hActiveThread, &titcontext, IndexOfRegister >= UE_MXCSR)) if(!_GetFullContextDataEx(hActiveThread, &titcontext, IndexOfRegister >= UE_MXCSR))
return false; return false;
bool avx_priority = false; bool avx_priority = false;
switch (IndexOfRegister) switch(IndexOfRegister)
{ {
case UE_X87_STATUSWORD: case UE_X87_STATUSWORD:
{ {
@ -481,7 +481,8 @@ public:
break; break;
} }
default: __debugbreak(); default:
__debugbreak();
} }
return _SetFullContextDataEx(hActiveThread, &titcontext, avx_priority); return _SetFullContextDataEx(hActiveThread, &titcontext, avx_priority);
@ -505,7 +506,7 @@ public:
DWORD x87r0_position = Getx87r0PositionInRegisterArea(STInTopStack); DWORD x87r0_position = Getx87r0PositionInRegisterArea(STInTopStack);
int i; int i;
for (i = 0; i < 8; i++) for(i = 0; i < 8; i++)
mmx[i] = *((uint64_t*)GetRegisterAreaOf87register(titcontext->RegisterArea, x87r0_position, i)); mmx[i] = *((uint64_t*)GetRegisterAreaOf87register(titcontext->RegisterArea, x87r0_position, i));
} }
@ -522,7 +523,7 @@ public:
int STInTopStack = GetSTInTOPStackFromStatusWord(titcontext->x87fpu.StatusWord); int STInTopStack = GetSTInTOPStackFromStatusWord(titcontext->x87fpu.StatusWord);
DWORD x87r0_position = Getx87r0PositionInRegisterArea(STInTopStack); 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); memcpy(x87FPURegisters[i].data, GetRegisterAreaOf87register(titcontext->RegisterArea, x87r0_position, i), 10);
x87FPURegisters[i].st_value = GetSTValueFromIndex(x87r0_position, i); x87FPURegisters[i].st_value = GetSTValueFromIndex(x87r0_position, i);
@ -595,15 +596,15 @@ public:
if(!found->second.pe->IsValidPe()) if(!found->second.pe->IsValidPe())
__debugbreak(); //return 0; __debugbreak(); //return 0;
if (AddressToConvert < FileMapVA) if(AddressToConvert < FileMapVA)
__debugbreak(); __debugbreak();
// convert: FileOffset -> VA // convert: FileOffset -> VA
auto offset = found->second.pe->ConvertOffsetToRva( auto offset = found->second.pe->ConvertOffsetToRva(
uint32( AddressToConvert - FileMapVA ) uint32(AddressToConvert - FileMapVA)
); );
if (offset == INVALID_VALUE) if(offset == INVALID_VALUE)
return 0; return 0;
else else
return ReturnType ? FileMapVA + offset : offset; return ReturnType ? FileMapVA + offset : offset;
@ -623,8 +624,8 @@ public:
) )
{ {
return ConvertVAtoFileOffsetEx( return ConvertVAtoFileOffsetEx(
FileMapVA ,0 ,0 , FileMapVA, 0, 0,
AddressToConvert, false, ReturnType ); AddressToConvert, false, ReturnType);
} }
//// ////
@ -652,15 +653,15 @@ public:
// Convert to RVA if needed // Convert to RVA if needed
auto RVA_ToConvert = AddressIsRVA ? auto RVA_ToConvert = AddressIsRVA ?
AddressToConvert : AddressToConvert :
AddressToConvert - ImageBase; AddressToConvert - ImageBase;
// convert: VA -> FileOffset // convert: VA -> FileOffset
auto offset = found->second.pe->ConvertRvaToOffset( auto offset = found->second.pe->ConvertRvaToOffset(
uint32( RVA_ToConvert ) uint32(RVA_ToConvert)
); );
if (offset == INVALID_VALUE) if(offset == INVALID_VALUE)
return 0; return 0;
else else
return ReturnType ? FileMapVA + offset : offset; return ReturnType ? FileMapVA + offset : offset;
@ -730,8 +731,8 @@ public:
__debugbreak(); //return 0; __debugbreak(); //return 0;
auto sections = found->second.pe->GetSections(); auto sections = found->second.pe->GetSections();
return found->second.pe->IsPe64() return found->second.pe->IsPe64()
? GetPE32DataW_impl(found->second.pe->GetNtHeaders64(), WhichSection, WhichData, sections) ? GetPE32DataW_impl(found->second.pe->GetNtHeaders64(), WhichSection, WhichData, sections)
: GetPE32DataW_impl(found->second.pe->GetNtHeaders32(), WhichSection, WhichData, sections); : GetPE32DataW_impl(found->second.pe->GetNtHeaders32(), WhichSection, WhichData, sections);
} }
ULONG_PTR GetPE32Data(const char* szFileName, DWORD WhichSection, DWORD WhichData) ULONG_PTR GetPE32Data(const char* szFileName, DWORD WhichSection, DWORD WhichData)
@ -752,8 +753,8 @@ public:
__debugbreak(); //return 0; __debugbreak(); //return 0;
auto sections = pe.GetSections(); auto sections = pe.GetSections();
return pe.IsPe64() return pe.IsPe64()
? GetPE32DataW_impl(pe.GetNtHeaders64(), WhichSection, WhichData, sections) ? GetPE32DataW_impl(pe.GetNtHeaders64(), WhichSection, WhichData, sections)
: GetPE32DataW_impl(pe.GetNtHeaders32(), WhichSection, WhichData, sections); : GetPE32DataW_impl(pe.GetNtHeaders32(), WhichSection, WhichData, sections);
} }
bool IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA) bool IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA)
@ -764,7 +765,7 @@ public:
//Software Breakpoints //Software Breakpoints
bool SetBPX(ULONG_PTR bpxAddress, DWORD bpxType, LPVOID bpxCallBack) bool SetBPX(ULONG_PTR bpxAddress, DWORD bpxType, LPVOID bpxCallBack)
{ {
if (!mProcess) if(!mProcess)
return false; return false;
return mProcess->SetBreakpoint(bpxAddress, [bpxCallBack](const BreakpointInfo &) return mProcess->SetBreakpoint(bpxAddress, [bpxCallBack](const BreakpointInfo &)
{ {
@ -774,7 +775,7 @@ public:
bool DeleteBPX(ULONG_PTR bpxAddress) bool DeleteBPX(ULONG_PTR bpxAddress)
{ {
if (!mProcess) if(!mProcess)
return false; return false;
return mProcess->DeleteBreakpoint(bpxAddress); return mProcess->DeleteBreakpoint(bpxAddress);
} }
@ -782,7 +783,7 @@ public:
bool IsBPXEnabled(ULONG_PTR bpxAddress) bool IsBPXEnabled(ULONG_PTR bpxAddress)
{ {
return (mProcess->MemIsValidPtr(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) void SetBPXOptions(long DefaultBreakPointType)
@ -792,7 +793,7 @@ public:
//Memory Breakpoints //Memory Breakpoints
bool SetMemoryBPXEx(ULONG_PTR MemoryStart, SIZE_T SizeOfMemory, DWORD BreakPointType, bool RestoreOnHit, LPVOID bpxCallBack) bool SetMemoryBPXEx(ULONG_PTR MemoryStart, SIZE_T SizeOfMemory, DWORD BreakPointType, bool RestoreOnHit, LPVOID bpxCallBack)
{ {
if (!mProcess) if(!mProcess)
return false; return false;
return mProcess->SetMemoryBreakpoint(ptr(MemoryStart), ptr(SizeOfMemory), [bpxCallBack](const BreakpointInfo & info) return mProcess->SetMemoryBreakpoint(ptr(MemoryStart), ptr(SizeOfMemory), [bpxCallBack](const BreakpointInfo & info)
{ {
@ -802,7 +803,7 @@ public:
bool RemoveMemoryBPX(ULONG_PTR MemoryStart, SIZE_T SizeOfMemory) bool RemoveMemoryBPX(ULONG_PTR MemoryStart, SIZE_T SizeOfMemory)
{ {
if (!mProcess) if(!mProcess)
return false; return false;
return mProcess->DeleteMemoryBreakpoint(ptr(MemoryStart)); return mProcess->DeleteMemoryBreakpoint(ptr(MemoryStart));
} }
@ -810,7 +811,7 @@ public:
//Hardware Breakpoints //Hardware Breakpoints
bool SetHardwareBreakPoint(ULONG_PTR bpxAddress, DWORD IndexOfRegister, DWORD bpxType, DWORD bpxSize, LPVOID bpxCallBack) bool SetHardwareBreakPoint(ULONG_PTR bpxAddress, DWORD IndexOfRegister, DWORD bpxType, DWORD bpxSize, LPVOID bpxCallBack)
{ {
if (!mProcess) if(!mProcess)
return false; return false;
auto running = mIsRunning; auto running = mIsRunning;
if(running) if(running)
@ -819,11 +820,11 @@ public:
thread.second->Suspend(); thread.second->Suspend();
} }
if(!mProcess->SetHardwareBreakpoint(bpxAddress, if(!mProcess->SetHardwareBreakpoint(bpxAddress,
(HardwareSlot)IndexOfRegister, [bpxCallBack](const BreakpointInfo & info) (HardwareSlot)IndexOfRegister, [bpxCallBack](const BreakpointInfo & info)
{ {
(HWBPCALLBACK(bpxCallBack))((const void*)info.address); (HWBPCALLBACK(bpxCallBack))((const void*)info.address);
}, hwtypeFromTitan(bpxType), hwsizeFromTitan(bpxSize))) }, hwtypeFromTitan(bpxType), hwsizeFromTitan(bpxSize)))
return false; return false;
if(running) if(running)
{ {
for(auto & thread : mProcess->threads) for(auto & thread : mProcess->threads)
@ -834,7 +835,7 @@ public:
bool DeleteHardwareBreakPoint(DWORD IndexOfRegister) bool DeleteHardwareBreakPoint(DWORD IndexOfRegister)
{ {
if (!mProcess || IndexOfRegister > 3) if(!mProcess || IndexOfRegister > 3)
return false; return false;
auto address = mProcess->hardwareBreakpoints[IndexOfRegister].address; auto address = mProcess->hardwareBreakpoints[IndexOfRegister].address;
return mProcess->DeleteHardwareBreakpoint(address); return mProcess->DeleteHardwareBreakpoint(address);
@ -842,11 +843,11 @@ public:
bool GetUnusedHardwareBreakPointRegister(LPDWORD RegisterIndex) bool GetUnusedHardwareBreakPointRegister(LPDWORD RegisterIndex)
{ {
if (!mProcess || !RegisterIndex) if(!mProcess || !RegisterIndex)
return false; return false;
HardwareSlot slot; HardwareSlot slot;
bool result = mProcess->GetFreeHardwareBreakpointSlot(slot); bool result = mProcess->GetFreeHardwareBreakpointSlot(slot);
if (result) if(result)
*RegisterIndex = (DWORD)slot; *RegisterIndex = (DWORD)slot;
return result; return result;
} }
@ -866,55 +867,55 @@ public:
protected: protected:
void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const Process & process) override void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const Process & process) override
{ {
if (mCbCREATEPROCESS) if(mCbCREATEPROCESS)
mCbCREATEPROCESS(&createProcess); mCbCREATEPROCESS(&createProcess);
} }
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const Process & process) override void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const Process & process) override
{ {
if (mCbEXITPROCESS) if(mCbEXITPROCESS)
mCbEXITPROCESS(&exitProcess); mCbEXITPROCESS(&exitProcess);
} }
void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const Thread & thread) override void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const Thread & thread) override
{ {
if (mCbCREATETHREAD) if(mCbCREATETHREAD)
mCbCREATETHREAD(&createThread); mCbCREATETHREAD(&createThread);
} }
void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const Thread & thread) override void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const Thread & thread) override
{ {
if (mCbEXITTHREAD) if(mCbEXITTHREAD)
mCbEXITTHREAD(&exitThread); mCbEXITTHREAD(&exitThread);
} }
void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) override void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) override
{ {
if (mCbLOADDLL) if(mCbLOADDLL)
mCbLOADDLL(&loadDll); mCbLOADDLL(&loadDll);
} }
void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll) override void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll) override
{ {
if (mCbUNLOADDLL) if(mCbUNLOADDLL)
mCbUNLOADDLL(&unloadDll); mCbUNLOADDLL(&unloadDll);
} }
void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) override void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) override
{ {
if (mCbUNHANDLEDEXCEPTION) if(mCbUNHANDLEDEXCEPTION)
mCbUNHANDLEDEXCEPTION(&mDebugEvent.u.Exception); mCbUNHANDLEDEXCEPTION(&mDebugEvent.u.Exception);
} }
void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) override void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) override
{ {
if (mCbOUTPUTDEBUGSTRING) if(mCbOUTPUTDEBUGSTRING)
mCbOUTPUTDEBUGSTRING(&debugString); mCbOUTPUTDEBUGSTRING(&debugString);
} }
void cbPreDebugEvent(const DEBUG_EVENT & debugEvent) override void cbPreDebugEvent(const DEBUG_EVENT & debugEvent) override
{ {
if (mCbDEBUGEVENT) if(mCbDEBUGEVENT)
mCbDEBUGEVENT(&debugEvent); mCbDEBUGEVENT(&debugEvent);
} }
@ -930,60 +931,103 @@ protected:
void cbSystemBreakpoint() override void cbSystemBreakpoint() override
{ {
if (mCbSYSTEMBREAKPOINT) if(mCbSYSTEMBREAKPOINT)
mCbSYSTEMBREAKPOINT(&mDebugEvent.u.Exception); mCbSYSTEMBREAKPOINT(&mDebugEvent.u.Exception);
} }
private: //functions private: //functions
inline Registers::R registerFromDword(DWORD IndexOfRegister) inline Registers::R registerFromDword(DWORD IndexOfRegister)
{ {
switch (IndexOfRegister) switch(IndexOfRegister)
{ {
case UE_EAX: return Registers::R::EAX; case UE_EAX:
case UE_EBX: return Registers::R::EBX; return Registers::R::EAX;
case UE_ECX: return Registers::R::ECX; case UE_EBX:
case UE_EDX: return Registers::R::EDX; return Registers::R::EBX;
case UE_EDI: return Registers::R::EDI; case UE_ECX:
case UE_ESI: return Registers::R::ESI; return Registers::R::ECX;
case UE_EBP: return Registers::R::EBP; case UE_EDX:
case UE_ESP: return Registers::R::ESP; return Registers::R::EDX;
case UE_EIP: return Registers::R::EIP; case UE_EDI:
case UE_EFLAGS: return Registers::R::EFlags; return Registers::R::EDI;
case UE_DR0: return Registers::R::DR0; case UE_ESI:
case UE_DR1: return Registers::R::DR1; return Registers::R::ESI;
case UE_DR2: return Registers::R::DR2; case UE_EBP:
case UE_DR3: return Registers::R::DR3; return Registers::R::EBP;
case UE_DR6: return Registers::R::DR6; case UE_ESP:
case UE_DR7: return Registers::R::DR7; 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 #ifdef _WIN64
case UE_RAX: return Registers::R::RAX; case UE_RAX:
case UE_RBX: return Registers::R::RBX; return Registers::R::RAX;
case UE_RCX: return Registers::R::RCX; case UE_RBX:
case UE_RDX: return Registers::R::RDX; return Registers::R::RBX;
case UE_RDI: return Registers::R::RDI; case UE_RCX:
case UE_RSI: return Registers::R::RSI; return Registers::R::RCX;
case UE_RBP: return Registers::R::RBP; case UE_RDX:
case UE_RSP: return Registers::R::RSP; return Registers::R::RDX;
case UE_RIP: return Registers::R::RIP; case UE_RDI:
case UE_RFLAGS: return Registers::R::EFlags; return Registers::R::RDI;
case UE_R8: return Registers::R::R8; case UE_RSI:
case UE_R9: return Registers::R::R9; return Registers::R::RSI;
case UE_R10: return Registers::R::R10; case UE_RBP:
case UE_R11: return Registers::R::R11; return Registers::R::RBP;
case UE_R12: return Registers::R::R12; case UE_RSP:
case UE_R13: return Registers::R::R13; return Registers::R::RSP;
case UE_R14: return Registers::R::R14; case UE_RIP:
case UE_R15: return Registers::R::R15; 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 #endif //_WIN64
case UE_CIP: return Registers::R::GIP; case UE_CIP:
case UE_CSP: return Registers::R::GSP; return Registers::R::GIP;
case UE_SEG_GS: return Registers::R::GS; case UE_CSP:
case UE_SEG_FS: return Registers::R::FS; return Registers::R::GSP;
case UE_SEG_ES: return Registers::R::ES; case UE_SEG_GS:
case UE_SEG_DS: return Registers::R::DS; return Registers::R::GS;
case UE_SEG_CS: return Registers::R::CS; case UE_SEG_FS:
case UE_SEG_SS: return Registers::R::SS; return Registers::R::FS;
default: return Registers::R::Invalid; 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) static HardwareType hwtypeFromTitan(DWORD type)
{ {
switch (type) switch(type)
{ {
case UE_HARDWARE_EXECUTE: case UE_HARDWARE_EXECUTE:
return HardwareType::Execute; return HardwareType::Execute;
@ -1052,7 +1096,7 @@ private: //functions
static HardwareSize hwsizeFromTitan(DWORD size) static HardwareSize hwsizeFromTitan(DWORD size)
{ {
switch (size) switch(size)
{ {
case UE_HARDWARE_SIZE_1: case UE_HARDWARE_SIZE_1:
return HardwareSize::SizeByte; return HardwareSize::SizeByte;
@ -1071,7 +1115,7 @@ private: //functions
static MemoryType memtypeFromTitan(DWORD type) static MemoryType memtypeFromTitan(DWORD type)
{ {
switch (type) switch(type)
{ {
case UE_MEMORY: case UE_MEMORY:
return MemoryType::Access; return MemoryType::Access;
@ -1209,18 +1253,18 @@ private: //functions
{ {
bool result = false; bool result = false;
HRSRC hResource = FindResourceA(engineHandle, (LPCSTR)szResourceName, "BINARY"); HRSRC hResource = FindResourceA(engineHandle, (LPCSTR)szResourceName, "BINARY");
if (hResource != NULL) if(hResource != NULL)
{ {
HGLOBAL hResourceGlobal = LoadResource(engineHandle, hResource); HGLOBAL hResourceGlobal = LoadResource(engineHandle, hResource);
if (hResourceGlobal != NULL) if(hResourceGlobal != NULL)
{ {
DWORD ResourceSize = SizeofResource(engineHandle, hResource); DWORD ResourceSize = SizeofResource(engineHandle, hResource);
LPVOID ResourceData = LockResource(hResourceGlobal); LPVOID ResourceData = LockResource(hResourceGlobal);
HANDLE hFile = CreateFileW(szExtractedFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 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; DWORD NumberOfBytesWritten;
if (WriteFile(hFile, ResourceData, ResourceSize, &NumberOfBytesWritten, NULL)) if(WriteFile(hFile, ResourceData, ResourceSize, &NumberOfBytesWritten, NULL))
result = true; result = true;
CloseHandle(hFile); CloseHandle(hFile);
} }
@ -1232,7 +1276,7 @@ private: //functions
bool TryExtractDllLoader(bool failedBefore = false) bool TryExtractDllLoader(bool failedBefore = false)
{ {
wchar_t* szPath = wcsrchr(szDebuggeeName, L'\\'); wchar_t* szPath = wcsrchr(szDebuggeeName, L'\\');
if (szPath) if(szPath)
szPath[1] = '\0'; szPath[1] = '\0';
wchar_t DLLLoaderName[64] = L""; wchar_t DLLLoaderName[64] = L"";
#ifdef _WIN64 #ifdef _WIN64
@ -1242,14 +1286,14 @@ private: //functions
#endif //_WIN64 #endif //_WIN64
wcscat_s(szDebuggeeName, DLLLoaderName); wcscat_s(szDebuggeeName, DLLLoaderName);
#ifdef _WIN64 #ifdef _WIN64
if (EngineExtractResource("LOADERX64", szDebuggeeName)) if(EngineExtractResource("LOADERX64", szDebuggeeName))
#else #else
if (EngineExtractResource("LOADERX86", szDebuggeeName)) if(EngineExtractResource("LOADERX86", szDebuggeeName))
#endif //_WIN64 #endif //_WIN64
return true; return true;
return !failedBefore && return !failedBefore &&
GetModuleFileNameW(engineHandle, szDebuggeeName, _countof(szDebuggeeName)) && GetModuleFileNameW(engineHandle, szDebuggeeName, _countof(szDebuggeeName)) &&
TryExtractDllLoader(true); TryExtractDllLoader(true);
} }
private: //variables private: //variables

View File

@ -145,43 +145,43 @@ SETXSTATEFEATURESMASK _SetXStateFeaturesMask = NULL;
static bool SetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext) static bool SetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext)
{ {
if (InitXState() == false) if(InitXState() == false)
return false; return false;
DWORD64 FeatureMask = _GetEnabledXStateFeatures(); DWORD64 FeatureMask = _GetEnabledXStateFeatures();
if ((FeatureMask & XSTATE_MASK_AVX) == 0) if((FeatureMask & XSTATE_MASK_AVX) == 0)
return false; return false;
DWORD ContextSize = 0; DWORD ContextSize = 0;
BOOL Success = _InitializeContext(NULL, BOOL Success = _InitializeContext(NULL,
CONTEXT_ALL | CONTEXT_XSTATE, CONTEXT_ALL | CONTEXT_XSTATE,
NULL, NULL,
&ContextSize); &ContextSize);
if ((Success == TRUE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) if((Success == TRUE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
return false; return false;
std::vector<unsigned char> dataBuffer; std::vector<unsigned char> dataBuffer;
dataBuffer.resize(ContextSize); dataBuffer.resize(ContextSize);
PVOID Buffer = dataBuffer.data(); PVOID Buffer = dataBuffer.data();
if (Buffer == NULL) if(Buffer == NULL)
return false; return false;
PCONTEXT Context; PCONTEXT Context;
Success = _InitializeContext(Buffer, Success = _InitializeContext(Buffer,
CONTEXT_ALL | CONTEXT_XSTATE, CONTEXT_ALL | CONTEXT_XSTATE,
&Context, &Context,
&ContextSize); &ContextSize);
if (Success == FALSE) if(Success == FALSE)
return false; return false;
if (_SetXStateFeaturesMask(Context, XSTATE_MASK_AVX) == FALSE) if(_SetXStateFeaturesMask(Context, XSTATE_MASK_AVX) == FALSE)
return false; return false;
if (GetThreadContext(hActiveThread, Context) == FALSE) if(GetThreadContext(hActiveThread, Context) == FALSE)
return false; return false;
if (_GetXStateFeaturesMask(Context, &FeatureMask) == FALSE) if(_GetXStateFeaturesMask(Context, &FeatureMask) == FALSE)
return false; return false;
DWORD FeatureLength; 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); XmmRegister_t* Avx = (XmmRegister_t*)_LocateXStateFeature(Context, XSTATE_AVX, NULL);
int NumberOfRegisters = FeatureLength / sizeof(Sse[0]); 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; 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; 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) static bool GetAVXContext(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext)
{ {
if (InitXState() == false) if(InitXState() == false)
return false; return false;
DWORD64 FeatureMask = _GetEnabledXStateFeatures(); DWORD64 FeatureMask = _GetEnabledXStateFeatures();
if ((FeatureMask & XSTATE_MASK_AVX) == 0) if((FeatureMask & XSTATE_MASK_AVX) == 0)
return false; return false;
DWORD ContextSize = 0; DWORD ContextSize = 0;
BOOL Success = _InitializeContext(NULL, BOOL Success = _InitializeContext(NULL,
CONTEXT_ALL | CONTEXT_XSTATE, CONTEXT_ALL | CONTEXT_XSTATE,
NULL, NULL,
&ContextSize); &ContextSize);
if ((Success == TRUE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) if((Success == TRUE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
return false; return false;
std::vector<unsigned char> dataBuffer; std::vector<unsigned char> dataBuffer;
dataBuffer.resize(ContextSize); dataBuffer.resize(ContextSize);
PVOID Buffer = dataBuffer.data(); PVOID Buffer = dataBuffer.data();
if (Buffer == NULL) if(Buffer == NULL)
return false; return false;
PCONTEXT Context; PCONTEXT Context;
Success = _InitializeContext(Buffer, Success = _InitializeContext(Buffer,
CONTEXT_ALL | CONTEXT_XSTATE, CONTEXT_ALL | CONTEXT_XSTATE,
&Context, &Context,
&ContextSize); &ContextSize);
if (Success == FALSE) if(Success == FALSE)
return false; return false;
if (_SetXStateFeaturesMask(Context, XSTATE_MASK_AVX) == FALSE) if(_SetXStateFeaturesMask(Context, XSTATE_MASK_AVX) == FALSE)
return false; return false;
if (GetThreadContext(hActiveThread, Context) == FALSE) if(GetThreadContext(hActiveThread, Context) == FALSE)
return false; return false;
if (_GetXStateFeaturesMask(Context, &FeatureMask) == FALSE) if(_GetXStateFeaturesMask(Context, &FeatureMask) == FALSE)
return false; return false;
DWORD FeatureLength; 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); XmmRegister_t* Avx = (XmmRegister_t*)_LocateXStateFeature(Context, XSTATE_AVX, NULL);
int NumberOfRegisters = FeatureLength / sizeof(Sse[0]); 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]; 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]; 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; DBGContext.ContextFlags = CONTEXT_ALL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
if (!GetThreadContext(hActiveThread, &DBGContext)) if(!GetThreadContext(hActiveThread, &DBGContext))
return false; return false;
DBGContext.EFlags = (DWORD)titcontext->eflags; DBGContext.EFlags = (DWORD)titcontext->eflags;
@ -356,7 +356,7 @@ bool _SetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcont
bool returnf = !!SetThreadContext(hActiveThread, &DBGContext); bool returnf = !!SetThreadContext(hActiveThread, &DBGContext);
if (AVX_PRIORITY) if(AVX_PRIORITY)
SetAVXContext(hActiveThread, titcontext); SetAVXContext(hActiveThread, titcontext);
return returnf; return returnf;

View File

@ -20,11 +20,11 @@ IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServiceP
{ {
OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 }; OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
DWORDLONG const dwlConditionMask = VerSetConditionMask( DWORDLONG const dwlConditionMask = VerSetConditionMask(
VerSetConditionMask( VerSetConditionMask(
VerSetConditionMask( VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL), 0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL), VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = wMajorVersion; osvi.dwMajorVersion = wMajorVersion;
osvi.dwMinorVersion = wMinorVersion; osvi.dwMinorVersion = wMinorVersion;
@ -41,163 +41,163 @@ IsWindowsVistaOrGreater()
static int getHeapFlagsOffset(bool x64) static int getHeapFlagsOffset(bool x64)
{ {
if (x64) //x64 offsets if(x64) //x64 offsets
{ {
if (IsWindowsVistaOrGreater()) if(IsWindowsVistaOrGreater())
{ {
return 0x70; return 0x70;
} }
else else
{ {
return 0x14; return 0x14;
} }
} }
else //x86 offsets else //x86 offsets
{ {
if (IsWindowsVistaOrGreater()) if(IsWindowsVistaOrGreater())
{ {
return 0x40; return 0x40;
} }
else else
{ {
return 0x0C; return 0x0C;
} }
} }
} }
static int getHeapForceFlagsOffset(bool x64) static int getHeapForceFlagsOffset(bool x64)
{ {
if (x64) //x64 offsets if(x64) //x64 offsets
{ {
if (IsWindowsVistaOrGreater()) if(IsWindowsVistaOrGreater())
{ {
return 0x74; return 0x74;
} }
else else
{ {
return 0x18; return 0x18;
} }
} }
else //x86 offsets else //x86 offsets
{ {
if (IsWindowsVistaOrGreater()) if(IsWindowsVistaOrGreater())
{ {
return 0x44; return 0x44;
} }
else else
{ {
return 0x10; return 0x10;
} }
} }
} }
static void* GetPEBLocation_(HANDLE hProcess) static void* GetPEBLocation_(HANDLE hProcess)
{ {
ULONG RequiredLen = 0; ULONG RequiredLen = 0;
void* PebAddress = 0; void* PebAddress = 0;
PROCESS_BASIC_INFORMATION myProcessBasicInformation[5] = { 0 }; PROCESS_BASIC_INFORMATION myProcessBasicInformation[5] = { 0 };
if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, sizeof(PROCESS_BASIC_INFORMATION), &RequiredLen) == 0) if(NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, sizeof(PROCESS_BASIC_INFORMATION), &RequiredLen) == 0)
{ {
PebAddress = (void*)myProcessBasicInformation->PebBaseAddress; PebAddress = (void*)myProcessBasicInformation->PebBaseAddress;
} }
else else
{ {
if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, RequiredLen, &RequiredLen) == 0) if(NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, RequiredLen, &RequiredLen) == 0)
{ {
PebAddress = (void*)myProcessBasicInformation->PebBaseAddress; PebAddress = (void*)myProcessBasicInformation->PebBaseAddress;
} }
} }
return PebAddress; return PebAddress;
} }
static bool PebPatchHeapFlags(PEB_CURRENT* peb, HANDLE hProcess) static bool PebPatchHeapFlags(PEB_CURRENT* peb, HANDLE hProcess)
{ {
#ifdef _WIN64 #ifdef _WIN64
const auto is_x64 = true; const auto is_x64 = true;
#else #else
const auto is_x64 = false; const auto is_x64 = false;
#endif #endif
std::vector<PVOID> heaps; std::vector<PVOID> heaps;
heaps.resize(peb->NumberOfHeaps); heaps.resize(peb->NumberOfHeaps);
if (ReadProcessMemory(hProcess, (PVOID)peb->ProcessHeaps, (PVOID)heaps.data(), heaps.size() * sizeof(PVOID), nullptr) == FALSE) if(ReadProcessMemory(hProcess, (PVOID)peb->ProcessHeaps, (PVOID)heaps.data(), heaps.size() * sizeof(PVOID), nullptr) == FALSE)
return false; return false;
std::basic_string<uint8_t> heap; std::basic_string<uint8_t> heap;
heap.resize(0x100); // hacky heap.resize(0x100); // hacky
for (DWORD i = 0; i < peb->NumberOfHeaps; i++) for(DWORD i = 0; i < peb->NumberOfHeaps; i++)
{ {
if (ReadProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE) if(ReadProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE)
return false; return false;
auto flags = (DWORD *)(heap.data() + getHeapFlagsOffset(is_x64)); auto flags = (DWORD*)(heap.data() + getHeapFlagsOffset(is_x64));
auto force_flags = (DWORD *)(heap.data() + getHeapForceFlagsOffset(is_x64)); auto force_flags = (DWORD*)(heap.data() + getHeapForceFlagsOffset(is_x64));
if (i == 0) if(i == 0)
{ {
// Default heap. // Default heap.
*flags &= HEAP_GROWABLE; *flags &= HEAP_GROWABLE;
} }
else else
{ {
// Flags from RtlCreateHeap/HeapCreate. // Flags from RtlCreateHeap/HeapCreate.
*flags &= (HEAP_GROWABLE | HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_CREATE_ENABLE_EXECUTE); *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) if(WriteProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE)
return false; return false;
} }
return true; return true;
} }
static bool FixPebInProcess(HANDLE hProcess) static bool FixPebInProcess(HANDLE hProcess)
{ {
PEB_CURRENT myPEB = { 0 }; PEB_CURRENT myPEB = { 0 };
SIZE_T ueNumberOfBytesRead = 0; SIZE_T ueNumberOfBytesRead = 0;
void* heapFlagsAddress = 0; void* heapFlagsAddress = 0;
DWORD heapFlags = 0; DWORD heapFlags = 0;
void* heapForceFlagsAddress = 0; void* heapForceFlagsAddress = 0;
DWORD heapForceFlags = 0; DWORD heapForceFlags = 0;
void* AddressOfPEB = GetPEBLocation(hProcess); void* AddressOfPEB = GetPEBLocation(hProcess);
if (!AddressOfPEB) if(!AddressOfPEB)
return false; return false;
if (ReadProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead)) if(ReadProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead))
{ {
myPEB.BeingDebugged = FALSE; myPEB.BeingDebugged = FALSE;
myPEB.NtGlobalFlag &= ~0x70; myPEB.NtGlobalFlag &= ~0x70;
#ifdef _WIN64 #ifdef _WIN64
heapFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapFlagsOffset(true)); heapFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapFlagsOffset(true));
heapForceFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapForceFlagsOffset(true)); heapForceFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapForceFlagsOffset(true));
#else #else
heapFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapFlagsOffset(false)); heapFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapFlagsOffset(false));
heapForceFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapForceFlagsOffset(false)); heapForceFlagsAddress = (void*)((LONG_PTR)myPEB.ProcessHeap + getHeapForceFlagsOffset(false));
#endif //_WIN64 #endif //_WIN64
ReadProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0); ReadProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0);
ReadProcessMemory(hProcess, heapForceFlagsAddress, &heapForceFlags, sizeof(DWORD), 0); ReadProcessMemory(hProcess, heapForceFlagsAddress, &heapForceFlags, sizeof(DWORD), 0);
heapFlags &= HEAP_GROWABLE; heapFlags &= HEAP_GROWABLE;
heapForceFlags = 0; heapForceFlags = 0;
WriteProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0); WriteProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0);
WriteProcessMemory(hProcess, heapForceFlagsAddress, &heapForceFlags, 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)) if(WriteProcessMemory(hProcess, AddressOfPEB, (void*)&myPEB, sizeof(PEB_CURRENT), &ueNumberOfBytesRead))
{ {
return true; return true;
} }
} }
return false; return false;
} }

View File

@ -23,12 +23,12 @@ static HANDLE WINAPI ProcessIdToHandle(IN DWORD dwProcessId)
ClientId.UniqueProcess = UlongToHandle(dwProcessId); ClientId.UniqueProcess = UlongToHandle(dwProcessId);
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
Status = NtOpenProcess(&Handle, Status = NtOpenProcess(&Handle,
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_READ |
PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION, PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION,
&ObjectAttributes, &ObjectAttributes,
&ClientId); &ClientId);
if (!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
/* Fail */ /* Fail */
BaseSetLastNTError(Status); BaseSetLastNTError(Status);
@ -51,7 +51,7 @@ static NTSTATUS CreateThreadSkipAttach(IN HANDLE ProcessHandle, IN PUSER_THREAD_
NTSTATUS Status; NTSTATUS Status;
HANDLE hThread; HANDLE hThread;
typedef NTSTATUS(NTAPI *t_NtCreateThreadEx)( typedef NTSTATUS(NTAPI * t_NtCreateThreadEx)(
PHANDLE /* ThreadHandle */, PHANDLE /* ThreadHandle */,
ACCESS_MASK /* DesiredAccess */, ACCESS_MASK /* DesiredAccess */,
POBJECT_ATTRIBUTES /* ObjectAttributes */, POBJECT_ATTRIBUTES /* ObjectAttributes */,
@ -63,40 +63,40 @@ static NTSTATUS CreateThreadSkipAttach(IN HANDLE ProcessHandle, IN PUSER_THREAD_
SIZE_T /* StackSize */, SIZE_T /* StackSize */,
SIZE_T /* MaximumStackSize */, SIZE_T /* MaximumStackSize */,
PPS_ATTRIBUTE_LIST /* AttributeList */ PPS_ATTRIBUTE_LIST /* AttributeList */
); );
auto p_NtCreateThreadEx = (t_NtCreateThreadEx)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx"); 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 // Based on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/339263/16/client/crashpad_client_win.cc#697
Status = p_NtCreateThreadEx(&hThread, Status = p_NtCreateThreadEx(&hThread,
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
nullptr, nullptr,
ProcessHandle, ProcessHandle,
StartRoutine, StartRoutine,
Argument, Argument,
THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH, THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH,
0, 0,
0x4000 /* PAGE_SIZE * 4 */, 0x4000 /* PAGE_SIZE * 4 */,
0x4000, 0x4000,
nullptr); nullptr);
} }
else else
{ {
CLIENT_ID ClientId; CLIENT_ID ClientId;
Status = RtlCreateUserThread(ProcessHandle, Status = RtlCreateUserThread(ProcessHandle,
NULL, NULL,
FALSE, FALSE,
0, 0,
0x4000, 0x4000,
0x4000 /* PAGE_SIZE * 4 */, 0x4000 /* PAGE_SIZE * 4 */,
StartRoutine, StartRoutine,
Argument, Argument,
&hThread, &hThread,
&ClientId); &ClientId);
} }
if (NT_SUCCESS(Status)) if(NT_SUCCESS(Status))
{ {
NtClose(hThread); NtClose(hThread);
} }
@ -108,11 +108,11 @@ static NTSTATUS NTAPI DbgUiIssueRemoteBreakin_(IN HANDLE Process)
{ {
PUSER_THREAD_START_ROUTINE RemoteBreakFunction = (PUSER_THREAD_START_ROUTINE)DbgUiRemoteBreakin; PUSER_THREAD_START_ROUTINE RemoteBreakFunction = (PUSER_THREAD_START_ROUTINE)DbgUiRemoteBreakin;
LPVOID RemoteMemory = VirtualAllocEx(Process, 0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READ); LPVOID RemoteMemory = VirtualAllocEx(Process, 0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READ);
if (RemoteMemory) if(RemoteMemory)
{ {
SIZE_T written = 0; SIZE_T written = 0;
unsigned char payload[] = { 0xCC, 0xC3 }; 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; RemoteBreakFunction = (PUSER_THREAD_START_ROUTINE)RemoteMemory;
} }
@ -133,11 +133,11 @@ static NTSTATUS NTAPI DbgUiDebugActiveProcess_(IN HANDLE Process)
return Status; return Status;
#if 0 #if 0
if (NT_SUCCESS(Status)) if(NT_SUCCESS(Status))
{ {
/* Now break-in the process */ /* Now break-in the process */
Status = DbgUiIssueRemoteBreakin_(Process); Status = DbgUiIssueRemoteBreakin_(Process);
if (!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
/* We couldn't break-in, cancel debugging */ /* We couldn't break-in, cancel debugging */
DbgUiStopDebugging(Process); DbgUiStopDebugging(Process);
@ -151,7 +151,7 @@ static NTSTATUS NTAPI DbgUiDebugActiveProcess_(IN HANDLE Process)
static NTSTATUS NTAPI DbgUiConnectToDbg_() static NTSTATUS NTAPI DbgUiConnectToDbg_()
{ {
if (NtCurrentTeb()->DbgSsReserved[1] != NULL) if(NtCurrentTeb()->DbgSsReserved[1] != NULL)
return STATUS_SUCCESS; return STATUS_SUCCESS;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
@ -164,7 +164,7 @@ BOOL WINAPI DebugActiveProcess_(IN DWORD dwProcessId)
{ {
/* Connect to the debugger */ /* Connect to the debugger */
NTSTATUS Status = DbgUiConnectToDbg_(); NTSTATUS Status = DbgUiConnectToDbg_();
if (!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
BaseSetLastNTError(Status); BaseSetLastNTError(Status);
return FALSE; return FALSE;
@ -172,7 +172,7 @@ BOOL WINAPI DebugActiveProcess_(IN DWORD dwProcessId)
/* Get the process handle */ /* Get the process handle */
HANDLE Handle = ProcessIdToHandle(dwProcessId); HANDLE Handle = ProcessIdToHandle(dwProcessId);
if (!Handle) if(!Handle)
{ {
return FALSE; return FALSE;
} }
@ -184,7 +184,7 @@ BOOL WINAPI DebugActiveProcess_(IN DWORD dwProcessId)
NtClose(Handle); NtClose(Handle);
/* Check if debugging worked */ /* Check if debugging worked */
if (!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
/* Fail */ /* Fail */
BaseSetLastNTError(Status); BaseSetLastNTError(Status);

View File

@ -306,7 +306,7 @@ BOOL WINAPI DllMain(
_In_ LPVOID lpvReserved _In_ LPVOID lpvReserved
) )
{ {
if (fdwReason == DLL_PROCESS_ATTACH) if(fdwReason == DLL_PROCESS_ATTACH)
emu.engineHandle = hinstDLL; emu.engineHandle = hinstDLL;
return TRUE; return TRUE;
} }

View File

@ -7,10 +7,10 @@
#else #else
# ifndef ZYDIS_EXPORT # ifndef ZYDIS_EXPORT
# ifdef Zydis_EXPORTS # ifdef Zydis_EXPORTS
/* We are building this library */ /* We are building this library */
# define ZYDIS_EXPORT # define ZYDIS_EXPORT
# else # else
/* We are using this library */ /* We are using this library */
# define ZYDIS_EXPORT # define ZYDIS_EXPORT
# endif # endif
# endif # endif

2
code-format.bat Normal file
View File

@ -0,0 +1,2 @@
@echo off
AStyleHelper\AStyleHelper.exe Silent