From 30217c92d485163560b237c7bae89504e108a854 Mon Sep 17 00:00:00 2001 From: gmh5225 <2315157@qq.com> Date: Sun, 19 Jun 2022 19:12:44 +0800 Subject: [PATCH] AStyle format --- AStyleHelper/AStyle.dll | Bin 0 -> 321976 bytes AStyleHelper/AStyleHelper.exe | Bin 0 -> 50376 bytes AStyleHelper/AStyleHelper.exe.config | 25 ++ GleeBug/Debugger.Loop.Exception.cpp | 144 ++++----- GleeBug/Debugger.Loop.Process.cpp | 22 +- GleeBug/Debugger.Loop.Thread.cpp | 9 +- GleeBug/Debugger.Loop.cpp | 40 +-- GleeBug/Debugger.Process.Breakpoint.cpp | 96 +++--- GleeBug/Debugger.Process.Memory.cpp | 38 +-- GleeBug/Debugger.Process.cpp | 6 +- GleeBug/Debugger.Process.h | 4 +- .../Debugger.Thread.HardwareBreakpoint.cpp | 106 +++---- GleeBug/Debugger.Thread.Registers.GetSet.cpp | 8 +- GleeBug/Debugger.Thread.Registers.Register.h | 4 +- GleeBug/Debugger.Thread.Registers.cpp | 4 +- GleeBug/Debugger.Thread.cpp | 6 +- GleeBug/Debugger.cpp | 30 +- GleeBug/Debugger.h | 10 +- GleeBug/Static.BufferFile.cpp | 16 +- GleeBug/Static.File.cpp | 20 +- GleeBug/Static.Pattern.cpp | 64 ++-- GleeBug/Static.Pe.Section.h | 8 +- GleeBug/Static.Pe.cpp | 70 ++--- GleeBug/Static.Region.h | 14 +- MyDebugger/MyDebugger.h | 78 ++--- MyDebugger/main.cpp | 36 +-- StaticEngine/Emulator.h | 85 +++--- StaticEngine/TitanEngineEmulator.cpp | 6 +- TitanEngineEmulator/Emulator.h | 282 ++++++++++-------- TitanEngineEmulator/Global.Engine.Context.cpp | 76 ++--- TitanEngineEmulator/Hider.h | 246 +++++++-------- TitanEngineEmulator/NativeAttach.h | 74 ++--- TitanEngineEmulator/TitanEngineEmulator.cpp | 2 +- TitanEngineEmulator/resource.h | 2 +- ZydisExportConfig.h | 10 +- 35 files changed, 857 insertions(+), 784 deletions(-) create mode 100644 AStyleHelper/AStyle.dll create mode 100644 AStyleHelper/AStyleHelper.exe create mode 100644 AStyleHelper/AStyleHelper.exe.config diff --git a/AStyleHelper/AStyle.dll b/AStyleHelper/AStyle.dll new file mode 100644 index 0000000000000000000000000000000000000000..9c2f52381b5b8e6d733b05b35b782a8c90b3e2e8 GIT binary patch literal 321976 zcmeFaeSB2a)i!)4nS_8NXV8FAq6r!?Hqi!&8kt}d2uW0g350|yU$)eakt)I�ofZ zCL!SvKki$p_O=vT+sC%H^{WUih6FT&iUMjaR%@|(+nok0)Gr|DJlD1MnaKo3?!M3S zd*8p_{C?SIe_ng9wfA0o?X~wgbM-a%80m Yv08OA0&`Bx$CiJdH$VGPgv{cz*y zp)Zfw6du^V&n}s{R>a8b=}R6$un^Cqw@U0P5Rj+;Tbo4JHWb*rOZFYFs8aP z4gbe4%#Nq+Gt$PK=Og$HI8vx|N^FIayB45{q)}p0IF^1CFjdbwPSf3)_lBG+& zjU?d-cq93UoAg(~dY61>(ap$69+6kZMR@+?xO|h6iv9myaA5QMo84Zu?is^qN(&SR z-Cl`^W_*HZGANpH2tE_Oo(yI+)S90eMj-T9x>r4XLz?l;?K=nkZO+{UylUdP10}>` zL^PuquEr~YPvbGgP!ou^fp~SP@QR-W-e((ummW~J0*?{VjB>aduL3@e#}q^T;}PI> z5zmzhZ!I#ZpA#=Fu%CF0h-N&*viOT;Y=BSWF~v|nB;G#aJrPJj@6+U81MxBf2Z+ar zXvTBomEi4wPvbGgP*)Pq_%-mZONCdy1$ddn%M2`920TVYGp54Tcz*aa9#af;6j0H4NVilKfVla*JU@I6{}`u!{}bSCAl{zqQ_x$FOlleNh6X&uV?;D# zAB>fP_8p!XpVp<0QT87L(lBcd6P zkv74596pW56hnQVc=^P;Hx=Ig-vjRw;$;NNiN}a&#!uup3UBHr;8hbZGcbpEjKF+@tML}Vr`yLA$Uow3AYNT6ye->-_t_J` zOAjnu4m?IgGj_t&c)Q`#cuax(`!Vpki04X$w-A-8pA#=D5Fj2Sq8S!kjkg>=jmH$o zKjQ5p-V@(W!N2{_0Iz{~nE`7#@EC#qg{$$51Rhf$|A=S&7I@dC!h0W+TxAl^9aup; zMqoYS+{Yi*BlvXtm;(8?9(ei08<7fcMK|y^J}&Kx5RVbjjJ0qz-aYVXJf=YY5wC)H z-QP+iW0i+Ihc@E*e?Qe%mi71%^PMu2~uTY}dGpT=Vf zO93>0{KV05b+*Ph4¬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 Ic*c9o4h_YWF#8 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%0DC*geJbC=;tjPuIGRBTypFFkt8b|PG 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 Ck05XW literal 0 HcmV?d00001 diff --git a/AStyleHelper/AStyleHelper.exe.config b/AStyleHelper/AStyleHelper.exe.config new file mode 100644 index 0000000..08a6dc5 --- /dev/null +++ b/AStyleHelper/AStyleHelper.exe.config @@ -0,0 +1,25 @@ + + + + +

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