diff --git a/AllocaFixer.cpp b/AllocaFixer.cpp index 840f69e..7ef9f40 100644 --- a/AllocaFixer.cpp +++ b/AllocaFixer.cpp @@ -18,7 +18,6 @@ #include #include "HexRaysUtil.hpp" #include -#include "Config.hpp" // Finds calls to alloca in a function's decompilation microcode, and // records the integer parameter from each call site. @@ -46,7 +45,7 @@ struct AllocaFixer : minsn_visitor_t #elif IDA_SDK_VERSION >= 720 mcallinfo_t *func = curins->d.f; #endif -if (func == NULL) +if (func == nullptr) { msg("[E] %a: curins->d.f was NULL?", curins->ea); return 0; @@ -102,7 +101,7 @@ void FixCallsToAllocaProbe() continue; func_t *f = get_func(xr.from); - if (f == NULL) + if (f == nullptr) { msg("[E] Call to alloca from %a is not within a function; will not be processed\n", xr.from); continue; @@ -120,7 +119,7 @@ void FixCallsToAllocaProbe() mba_ranges_t mbr(f); hexrays_failure_t hf; mbl_array_t *mba = gen_microcode(mbr, &hf); - if (mba == NULL) + if (mba == nullptr) { msg("[E] FixCallsToAllocaProbe(%a): decompilation failed (%s)\n", f->start_ea, hf.desc().c_str()); continue; diff --git a/CFFlattenInfo.cpp b/CFFlattenInfo.cpp index f841137..74025ee 100644 --- a/CFFlattenInfo.cpp +++ b/CFFlattenInfo.cpp @@ -77,7 +77,7 @@ bool JZInfo::ShouldBlacklist() // thing being compared, we use a JZInfo structure to collect the number of // times it's been used in a comparison, and a list of the values it was // compared against. -struct JZCollector : public minsn_visitor_t +struct JZCollector : minsn_visitor_t { std::vector m_SeenComparisons; int m_nMaxJz; @@ -155,7 +155,7 @@ mblock_t *GetFirstBlock(mbl_array_t *mba, int &iFirst, int &iDispatch) #if UNFLATTENVERBOSE debugmsg("[E] Block %d had %d (!= 1) successors\n", iCurr, mb->nsucc()); #endif - return NULL; + return nullptr; } // Get the successor block @@ -178,7 +178,7 @@ mblock_t *GetFirstBlock(mbl_array_t *mba, int &iFirst, int &iDispatch) // This class is used to find all variables that have 32-bit numeric values // assigned to them in the first block (as well as the values that are // assigned to them). -struct BlockInsnAssignNumberExtractor : public minsn_visitor_t +struct BlockInsnAssignNumberExtractor : minsn_visitor_t { std::vector > m_SeenAssignments; int visit_minsn() @@ -199,7 +199,7 @@ struct BlockInsnAssignNumberExtractor : public minsn_visitor_t // block. This class is used to locate the "update" variable, by simply looking // for a variable whose contents are copied into the "comparison" variable, // which must have had a number assigned to it in the first block. -struct HandoffVarFinder : public minsn_visitor_t +struct HandoffVarFinder : minsn_visitor_t { // We're looking for assignments to this variable mop_t *m_ComparisonVar; @@ -253,7 +253,7 @@ struct HandoffVarFinder : public minsn_visitor_t // Once we know which variable is the one used for comparisons, look for all // jz instructions that compare a number against this variable. This then tells // us which number corresponds to which basic block. -struct JZMapper : public minsn_visitor_t +struct JZMapper : minsn_visitor_t { std::map &m_KeyToBlock; std::map &m_BlockToKey; @@ -438,7 +438,7 @@ bool CFFlattenInfo::GetAssignedAndComparisonVariables(mblock_t *blk) // Find the "first" block in the function, the one immediately before the // control flow switch. mblock_t *first = GetFirstBlock(mba, this->iFirst, this->iDispatch); - if (first == NULL) + if (first == nullptr) { #if UNFLATTENVERBOSE debugmsg("[E] Can't find top-level block in function\n"); diff --git a/CFFlattenInfo.hpp b/CFFlattenInfo.hpp index c68c91b..1accfb3 100644 --- a/CFFlattenInfo.hpp +++ b/CFFlattenInfo.hpp @@ -3,7 +3,7 @@ struct JZInfo { - JZInfo() : op(NULL) {}; + JZInfo() : op(nullptr) {}; mop_t *op; int nSeen; @@ -26,25 +26,25 @@ struct CFFlattenInfo int FindBlockByKey(uint64 key); void Clear(bool bFree) { - if (bFree && opAssigned != NULL) + if (bFree && opAssigned != nullptr) delete opAssigned; - opAssigned = NULL; + opAssigned = nullptr; - if (bFree && opCompared != NULL) + if (bFree && opCompared != nullptr) delete opCompared; - opCompared = NULL; + opCompared = nullptr; iFirst = -1; iDispatch = -1; uFirst = 0LL; m_WhichFunc = BADADDR; - if (bFree && m_DomInfo != NULL) + if (bFree && m_DomInfo != nullptr) delete m_DomInfo; - m_DomInfo = NULL; + m_DomInfo = nullptr; - if (bFree && m_DominatedClusters != NULL) + if (bFree && m_DominatedClusters != nullptr) delete m_DominatedClusters; - m_DominatedClusters = NULL; + m_DominatedClusters = nullptr; m_KeyToBlock.clear(); m_BlockToKey.clear(); diff --git a/DefUtil.cpp b/DefUtil.cpp index 569c3fe..c802bf6 100644 --- a/DefUtil.cpp +++ b/DefUtil.cpp @@ -44,13 +44,13 @@ bool InsertOp(mblock_t *mb, mlist_t &ml, mop_t *op) minsn_t *my_find_def_backwards(mblock_t *mb, mlist_t &ml, minsn_t *start) { minsn_t *mend = mb->head; - for (minsn_t *p = start != NULL ? start : mb->tail; p != NULL; p = p->prev) + for (minsn_t *p = start != nullptr ? start : mb->tail; p != nullptr; p = p->prev) { mlist_t def = mb->build_def_list(*p, MAY_ACCESS | FULL_XDSU); if (def.includes(ml)) return p; } - return NULL; + return nullptr; } // This is a nearly identical version of the function above, except it works @@ -58,13 +58,13 @@ minsn_t *my_find_def_backwards(mblock_t *mb, mlist_t &ml, minsn_t *start) minsn_t *my_find_def_forwards(mblock_t *mb, mlist_t &ml, minsn_t *start) { minsn_t *mend = mb->head; - for (minsn_t *p = start != NULL ? start : mb->head; p != NULL; p = p->next) + for (minsn_t *p = start != nullptr ? start : mb->head; p != nullptr; p = p->next) { mlist_t def = mb->build_def_list(*p, MAY_ACCESS | FULL_XDSU); if (def.includes(ml)) return p; } - return NULL; + return nullptr; } @@ -93,7 +93,7 @@ bool FindNumericDefBackwards(mblock_t *blk, mop_t *op, mop_t *&opNum, MovChain & // Start from the end of the block. This variable gets updated when a copy // is encountered, so that subsequent searches start from the right place. - minsn_t *mStart = NULL; + minsn_t *mStart = nullptr; do { // Told you this function was just a wrapper around @@ -101,7 +101,7 @@ bool FindNumericDefBackwards(mblock_t *blk, mop_t *op, mop_t *&opNum, MovChain & minsn_t *mDef = my_find_def_backwards(blk, ml, mStart); // If we did find a definition... - if (mDef != NULL) + if (mDef != nullptr) { // Ensure that it's a mov instruction. We don't want, for example, // an "stx" instruction, which is assumed to redefine everything @@ -174,7 +174,7 @@ bool FindNumericDefBackwards(mblock_t *blk, mop_t *op, mop_t *&opNum, MovChain & return false; // Resume the search at the end of the new block. - mStart = NULL; + mStart = nullptr; } } while (true); return false; @@ -186,11 +186,11 @@ mop_t *FindForwardNumericDef(mblock_t *blk, mop_t *mop, minsn_t *&assign_insn) { mlist_t ml; if (!InsertOp(blk, ml, mop)) - return NULL; + return nullptr; // Find a forward definition - assign_insn = my_find_def_forwards(blk, ml, NULL); - if (assign_insn != NULL) + assign_insn = my_find_def_forwards(blk, ml, nullptr); + if (assign_insn != nullptr) { #if UNFLATTENVERBOSE @@ -202,12 +202,12 @@ mop_t *FindForwardNumericDef(mblock_t *blk, mop_t *mop, minsn_t *&assign_insn) // We only want MOV instructions with numeric left-hand sides if (assign_insn->opcode != m_mov || assign_insn->l.t != mop_n) - return NULL; + return nullptr; // Return the numeric operand if we found it return &assign_insn->l; } - return NULL; + return nullptr; } // This function is just a thin wrapper around FindForwardNumericDef, which @@ -215,15 +215,15 @@ mop_t *FindForwardNumericDef(mblock_t *blk, mop_t *mop, minsn_t *&assign_insn) mop_t *FindForwardStackVarDef(mblock_t *mbClusterHead, mop_t *opCopy, MovChain &chain) { // Must be a non-NULL stack variable - if (opCopy == NULL || opCopy->t != mop_S) - return NULL; + if (opCopy == nullptr || opCopy->t != mop_S) + return nullptr; minsn_t *ins; // Find the definition mop_t *num = FindForwardNumericDef(mbClusterHead, opCopy, ins); - if (num == NULL) - return NULL; + if (num == nullptr) + return nullptr; #if UNFLATTENVERBOSE qstring qs; diff --git a/HexRaysDeob.vcxproj b/HexRaysDeob.vcxproj index 7529a98..3d1376d 100644 --- a/HexRaysDeob.vcxproj +++ b/HexRaysDeob.vcxproj @@ -1,200 +1,223 @@ - - - - - ida32 Debug - Win32 - - - ida64 Debug - Win32 - - - ida64 Debug - x64 - - - Release - Win32 - - - ida32 Debug - x64 - - - Release - x64 - - - - 15.0 - {5EF5C070-D860-43CF-A65C-3934E448C8F2} - Win32Proj - 8.1 - - - - Application - true - v141 - - - Application - true - v141 - - - Application - false - v141 - - - DynamicLibrary - true - v141 - - - DynamicLibrary - true - v141 - - - Application - false - v141 - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(VC_IncludePath);$(WindowsSDK_IncludePath);c:\work\src\idasdk72\include - - - true - $(VC_IncludePath);$(WindowsSDK_IncludePath);c:\work\src\idasdk72\include - - - true - - - $(VC_IncludePath);$(WindowsSDK_IncludePath);c:\work\src\idasdk72\include - - - $(VC_IncludePath);$(WindowsSDK_IncludePath);c:\work\src\idasdk72\include - - - - WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level3 - ProgramDatabase - Disabled - - - MachineX86 - true - Windows - - - - - WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level3 - ProgramDatabase - Disabled - - - MachineX86 - true - Windows - - - - - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level3 - ProgramDatabase - - - MachineX86 - true - Windows - true - true - - - - - MultiThreadedDLL - _WINDLL;%(PreprocessorDefinitions);__NT__;__IDP__;__X64__ - - - $(OutDir)\$(ProjectName).dll - /EXPORT:PLUGIN %(AdditionalOptions) - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);c:\work\src\idasdk72\lib\x64_win_vc_32\ida.lib - DebugFull - - - - - MultiThreadedDLL - _WINDLL;%(PreprocessorDefinitions);__NT__;__IDP__;__X64__;__EA64__; - - - $(OutDir)\$(ProjectName).dll - /EXPORT:PLUGIN %(AdditionalOptions) - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);c:\work\src\idasdk72\lib\x64_win_vc_64\ida.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + ida32 Debug + Win32 + + + ida64 Debug + Win32 + + + ida64 Debug + x64 + + + Release + Win32 + + + ida32 Debug + x64 + + + Release + x64 + + + + 15.0 + {5EF5C070-D860-43CF-A65C-3934E448C8F2} + Win32Proj + 8.1 + + + + Application + true + v141 + + + Application + true + v141 + + + Application + false + v141 + + + DynamicLibrary + true + v141 + + + DynamicLibrary + true + v141 + + + DynamicLibrary + false + v141 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(VC_IncludePath);$(WindowsSDK_IncludePath) + + + true + $(VC_IncludePath);$(WindowsSDK_IncludePath) + + + true + + + $(VC_IncludePath);$(WindowsSDK_IncludePath) + $(IDADIR)\plugins\ + + + $(VC_IncludePath);$(WindowsSDK_IncludePath) + $(IDADIR)\plugins\ + + + $(IDADIR)\plugins\ + + + + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + + + + + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + + + + + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + true + true + + + + + MultiThreadedDLL + _WINDLL;%(PreprocessorDefinitions);__NT__;__IDP__;__X64__ + $(IDASDK)\include;$(IDADIR)\plugins\hexrays_sdk\include;%(AdditionalIncludeDirectories) + + + Console + true + ida.lib;user32.lib;%(AdditionalDependencies) + /EXPORT:PLUGIN %(AdditionalOptions) + $(IDASDK)\lib\x64_win_vc_$(PlatformArchitecture) + DebugFull + + + + + MultiThreadedDLL + _WINDLL;%(PreprocessorDefinitions);__NT__;__IDP__;__X64__;__EA64__; + $(IDASDK)\include;$(IDADIR)\plugins\hexrays_sdk\include;%(AdditionalIncludeDirectories) + + + Console + true + ida.lib;user32.lib;%(AdditionalDependencies) + /EXPORT:PLUGIN %(AdditionalOptions) + $(IDASDK)\lib\x64_win_vc_$(PlatformArchitecture) + + + + + $(IDASDK)\include;$(IDADIR)\plugins\hexrays_sdk\include;%(AdditionalIncludeDirectories) + + + $(TargetPath) + $(IDASDK)\lib\x64_win_vc_$(PlatformArchitecture) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HexRaysDeob.vcxproj.user b/HexRaysDeob.vcxproj.user index f64f83d..7f1b1bd 100644 --- a/HexRaysDeob.vcxproj.user +++ b/HexRaysDeob.vcxproj.user @@ -1,11 +1,15 @@ - - - - C:\Program Files\IDA 7.2\ida.exe - WindowsLocalDebugger - - - c:\Program Files\IDA 7.2\ida64.exe - WindowsLocalDebugger - + + + + $(IDADIR)\ida64.exe + WindowsLocalDebugger + + + $(IDADIR)\ida64.exe + WindowsLocalDebugger + + + $(IDADIR)\ida64.exe + WindowsLocalDebugger + \ No newline at end of file diff --git a/MicrocodeExplorer.cpp b/MicrocodeExplorer.cpp index 02163ac..f866425 100644 --- a/MicrocodeExplorer.cpp +++ b/MicrocodeExplorer.cpp @@ -5,7 +5,7 @@ typedef std::shared_ptr shared_mbl_array_t; -struct mblock_virtual_dumper_t : public vd_printer_t +struct mblock_virtual_dumper_t : vd_printer_t { int nline; int serial; @@ -32,7 +32,7 @@ struct mblock_virtual_dumper_t : public vd_printer_t } }; -struct mblock_qstring_dumper_t : public mblock_virtual_dumper_t +struct mblock_qstring_dumper_t : mblock_virtual_dumper_t { qstring qStr; mblock_qstring_dumper_t() : mblock_virtual_dumper_t() {}; @@ -42,7 +42,7 @@ struct mblock_qstring_dumper_t : public mblock_virtual_dumper_t } }; -struct mblock_dumper_t : public mblock_virtual_dumper_t +struct mblock_dumper_t : mblock_virtual_dumper_t { strvec_t lines; mblock_dumper_t() : mblock_virtual_dumper_t() {}; @@ -58,7 +58,7 @@ struct sample_info_t mblock_dumper_t md; shared_mbl_array_t mba; mba_maturity_t mat; - sample_info_t() : cv(NULL), mba(NULL) {} + sample_info_t() : cv(nullptr), mba(nullptr) {} }; #include @@ -177,7 +177,7 @@ class MicrocodeInstructionGraphContainer public: MicrocodeInstructionGraph m_MG; - MicrocodeInstructionGraphContainer() : m_TW(NULL), m_GV(NULL) {}; + MicrocodeInstructionGraphContainer() : m_TW(nullptr), m_GV(nullptr) {}; bool Display(minsn_t *top, sample_info_t *si, int nBlock, int nSerial) { @@ -227,7 +227,7 @@ static ssize_t idaapi migr_callback(void *ud, int code, va_list va) mg->resize(microg->m_NumBlocks); for (auto &it : microg->m_Edges) - mg->add_edge(it.src, it.dst, NULL); + mg->add_edge(it.src, it.dst, nullptr); result = true; } @@ -317,7 +317,7 @@ static ssize_t idaapi mgr_callback(void *ud, int code, va_list va) for (int i = 0; i < mba->qty; ++i) for (auto dst : mba->get_mblock(i)->succset) - mg->add_edge(i, dst, NULL); + mg->add_edge(i, dst, nullptr); result = true; } @@ -367,7 +367,7 @@ static bool idaapi ct_keyboard(TWidget * /*v*/, int key, int shift, void *ud) tag_remove(&buf, get_custom_viewer_curline(si->cv, false)); const char *pLine = buf.c_str(); const char *pDot = strchr(pLine, '.'); - if (pDot == NULL) + if (pDot == nullptr) { warning( "Couldn't find the block number on the current line; was the block empty?\n" @@ -392,11 +392,11 @@ static bool idaapi ct_keyboard(TWidget * /*v*/, int key, int shift, void *ud) for (i = 0; i < nSerial; ++i) { minsn = minsn->next; - if (minsn == NULL) + if (minsn == nullptr) break; } - if (minsn == NULL) + if (minsn == nullptr) { if (i == 0) warning( @@ -424,14 +424,14 @@ static bool idaapi ct_keyboard(TWidget * /*v*/, int key, int shift, void *ud) static const custom_viewer_handlers_t handlers( ct_keyboard, - NULL, // popup - NULL, // mouse_moved - NULL, // click - NULL, // dblclick - NULL, - NULL, // close - NULL, // help - NULL);// adjust_place + nullptr, // popup + nullptr, // mouse_moved + nullptr, // click + nullptr, // dblclick + nullptr, + nullptr, // close + nullptr, // help + nullptr);// adjust_place ssize_t idaapi ui_callback(void *ud, int code, va_list va) { @@ -485,7 +485,7 @@ mba_maturity_t AskDesiredMaturity() void ShowMicrocodeExplorer() { func_t *pfn = get_func(get_screen_ea()); - if (pfn == NULL) + if (pfn == nullptr) { warning("Please position the cursor within a function"); return; @@ -496,8 +496,8 @@ void ShowMicrocodeExplorer() return; hexrays_failure_t hf; - mbl_array_t *mba = gen_microcode(pfn, &hf, NULL, 0, mmat); - if (mba == NULL) + mbl_array_t *mba = gen_microcode(pfn, &hf, nullptr, 0, mmat); + if (mba == nullptr) { warning("#error \"%a: %s", hf.errea, hf.desc().c_str()); return; @@ -520,11 +520,11 @@ void ShowMicrocodeExplorer() &s1, // minplace &s2, // maxplace &s1, // curplace - NULL, // renderer_info_t *rinfo + nullptr, // renderer_info_t *rinfo &si->md.lines, // ud &handlers, // cvhandlers si, // cvhandlers_ud - NULL); // parent + nullptr); // parent hook_to_notification_point(HT_UI, ui_callback, si); #if IDA_SDK_VERSION >= 730 diff --git a/PatternDeobfuscate.cpp b/PatternDeobfuscate.cpp index ae2a853..3fbd4f8 100644 --- a/PatternDeobfuscate.cpp +++ b/PatternDeobfuscate.cpp @@ -6,7 +6,7 @@ // Our pattern-based deobfuscation is implemented as an optinsn_t structure, // which allows us to hook directly into the microcode generation phase and // perform optimizations automatically, whenever code is decompiled. -struct ObfCompilerOptimizer : public optinsn_t +struct ObfCompilerOptimizer : optinsn_t { // This function simplifies microinstruction patterns that look like // either: (x & 1) | (y & 1) ==> (x | y) & 1 @@ -76,7 +76,7 @@ struct ObfCompilerOptimizer : public optinsn_t return false; // Extract x and (y-z) - mop_t *opAddNum = NULL, *opAddNonNum = NULL; + mop_t *opAddNum = nullptr, *opAddNonNum = nullptr; if (!ExtractNumAndNonNum(ins, opAddNum, opAddNonNum)) return false; @@ -87,7 +87,7 @@ struct ObfCompilerOptimizer : public optinsn_t // Extract y and z. I guess technically I shouldn't use // ExtractNumAndNonNum here since subtraction isn't commutative... // Call that a bug, but it didn't matter in practice. - mop_t *opSubNum = NULL, *opSubNonNum = NULL; + mop_t *opSubNum = nullptr, *opSubNonNum = nullptr; if (!ExtractNumAndNonNum(opAddNonNum->d, opSubNum, opSubNonNum)) return false; @@ -277,10 +277,10 @@ struct ObfCompilerOptimizer : public optinsn_t return 0; // Extract the numeric and non-numeric operands from both AND terms - mop_t *lhsNum = NULL, *rhsNum = NULL; - mop_t *lhsNonNum = NULL, *rhsNonNum = NULL; - bool bLhsSucc = ExtractNumAndNonNum(lhs1, lhsNum, lhsNonNum); - bool bRhsSucc = ExtractNumAndNonNum(rhs1, rhsNum, rhsNonNum); + mop_t *lhsNum = nullptr, *rhsNum = nullptr; + mop_t *lhsNonNum = nullptr, *rhsNonNum = nullptr; + bool bLhsSucc = ExtractNumAndNonNum(lhs1, lhsNum, lhsNonNum); + bool bRhsSucc = ExtractNumAndNonNum(rhs1, rhsNum, rhsNonNum); // ... both AND terms must have one constant ... if (!bLhsSucc || !bRhsSucc) @@ -295,8 +295,8 @@ struct ObfCompilerOptimizer : public optinsn_t return 0; // One of the non-numeric parts must have a binary not (i.e., ~) on it - minsn_t *sourceOfResult = NULL; - mop_t *nonNottedInsn = NULL, *nottedNum = NULL, *nottedInsn = NULL; + minsn_t *sourceOfResult = nullptr; + mop_t *nonNottedInsn = nullptr, *nottedNum = nullptr, *nottedInsn = nullptr; // Check the left-hand size for binary not if (lhsNonNum->t == mop_d && lhsNonNum->d->opcode == m_bnot) @@ -313,7 +313,7 @@ struct ObfCompilerOptimizer : public optinsn_t if (rhsNonNum->t == mop_d && rhsNonNum->d->opcode == m_bnot) { // Both sides NOT? Not what we want, return 0 - if (nottedInsn != NULL) + if (nottedInsn != nullptr) return 0; // Extract the NOTed term @@ -324,7 +324,7 @@ struct ObfCompilerOptimizer : public optinsn_t else { // Neither side has a NOT? Bail - if (nonNottedInsn != NULL) + if (nonNottedInsn != nullptr) return 0; nonNottedInsn = rhsNonNum; } @@ -398,7 +398,7 @@ struct ObfCompilerOptimizer : public optinsn_t // Find and return it if that's the case. mop_t *FindNonCommonConstant(std::set *smaller, std::set *bigger) { - mop_t *noMatch = NULL; + mop_t *noMatch = nullptr; // Iterate through the larger set for (auto eL : *bigger) { @@ -419,8 +419,8 @@ struct ObfCompilerOptimizer : public optinsn_t // If noMatch was not NULL, then there was more than one // constant in the larger set that wasn't in the smaller one, // so return NULL on failure. - if (noMatch != NULL) - return 0; + if (noMatch != nullptr) + return nullptr; noMatch = eL; } @@ -482,7 +482,7 @@ struct ObfCompilerOptimizer : public optinsn_t mop_t *noMatch = FindNonCommonConstant(smaller, bigger); // If there wasn't one, the pattern failed, so return 0 - if (noMatch == NULL) + if (noMatch == nullptr) return 0; // Invert the non-common number and truncate it down to its proper size @@ -503,7 +503,7 @@ struct ObfCompilerOptimizer : public optinsn_t { // The whole expression must be logically negated. minsn_t *inner; - if (!ExtractLogicallyNegatedTerm(ins, inner) || inner == NULL) + if (!ExtractLogicallyNegatedTerm(ins, inner) || inner == nullptr) return 0; // The thing that was negated must be an OR with compound operands. @@ -599,11 +599,20 @@ struct ObfCompilerOptimizer : public optinsn_t // This is the virtual function dictated by the optinsn_t interface. This // function gets called by the Hex-Rays kernel; we optimize the microcode. +#if IDA_SDK_VERSION <= 730 int func(mblock_t *blk, minsn_t *ins); +#else + int func(mblock_t* blk, minsn_t* ins, int optflags) override; +#endif }; // Callback function. Do pattern-deobfuscation. +#if IDA_SDK_VERSION <= 730 int ObfCompilerOptimizer::func(mblock_t *blk, minsn_t *ins) +#else +int ObfCompilerOptimizer::func(mblock_t* blk, minsn_t* ins, int optflags) +#endif + { #if OPTVERBOSE char buf[1000]; diff --git a/PatternDeobfuscate.hpp b/PatternDeobfuscate.hpp index cf7d2e5..55f9e11 100644 --- a/PatternDeobfuscate.hpp +++ b/PatternDeobfuscate.hpp @@ -1,7 +1,12 @@ #pragma once #include -struct ObfCompilerOptimizer : public optinsn_t +struct ObfCompilerOptimizer : optinsn_t { +// sfink - i'm not actually sure when the signature changed, but i'm assuming later than 730 +#if IDA_SDK_VERSION <= 730 int func(mblock_t *blk, minsn_t *ins); +#else + int func(mblock_t* blk, minsn_t* ins, int optflags) override; +#endif }; diff --git a/PatternDeobfuscateUtil.cpp b/PatternDeobfuscateUtil.cpp index 3a6ad90..e4c48d4 100644 --- a/PatternDeobfuscateUtil.cpp +++ b/PatternDeobfuscateUtil.cpp @@ -11,7 +11,7 @@ // deobfuscations. bool ExtractNumAndNonNum(minsn_t *insn, mop_t *&numOp, mop_t *&otherOp) { - mop_t *num = NULL, *other = NULL; + mop_t *num = nullptr, *other = nullptr; if (insn->l.t == mop_n) { @@ -21,7 +21,7 @@ bool ExtractNumAndNonNum(minsn_t *insn, mop_t *&numOp, mop_t *&otherOp) if (insn->r.t == mop_n) { - if (num != NULL) + if (num != nullptr) { // Technically we have an option to perform constant folding // here... but Hex-Rays should have done / should do that for us @@ -30,7 +30,7 @@ bool ExtractNumAndNonNum(minsn_t *insn, mop_t *&numOp, mop_t *&otherOp) num = &insn->r; other = &insn->l; } - if (num == NULL) + if (num == nullptr) return false; numOp = num; @@ -50,8 +50,8 @@ bool ExtractNumAndNonNum(minsn_t *insn, mop_t *&numOp, mop_t *&otherOp) // side, and once for when the operation was on the right-hand side. bool ExtractByOpcodeType(minsn_t *ins, mcode_t mc, minsn_t *&match, mop_t*& noMatch) { - mop_t *possNoMatch = NULL; - minsn_t *possMatch = NULL; + mop_t *possNoMatch = nullptr; + minsn_t *possMatch = nullptr; // Does the left-hand side contain the operation we're looking for? // Update possNoMatch or possMatch, depending. @@ -67,7 +67,7 @@ bool ExtractByOpcodeType(minsn_t *ins, mcode_t mc, minsn_t *&match, mop_t*& noMa possMatch = ins->r.d; // If both sides matched, or neither side matched, fail. - if (possNoMatch == NULL || possMatch == NULL) + if (possNoMatch == nullptr || possMatch == nullptr) return false; match = possMatch; @@ -101,7 +101,7 @@ bool TunnelThroughAnd1(minsn_t *ins, minsn_t *&inner, bool bRequireSize1, mop_t return false; // If requested, pass the operand back to the caller this point - if(opInner != NULL) + if(opInner != nullptr) *opInner = andNonNum; // If the non-numeric operand is an instruction, extract the @@ -115,7 +115,7 @@ bool TunnelThroughAnd1(minsn_t *ins, minsn_t *&inner, bool bRequireSize1, mop_t // Otherwise, if the non-numeric part wasn't a mop_d, check to see whether // the caller specifically wanted a mop_d. If they did, fail. If the caller // was willing to accept another operand type, return true. - return opInner != NULL; + return opInner != nullptr; } // The obfuscator implements boolean inversion via "x ^ 1". Hex-Rays, or one of @@ -132,7 +132,7 @@ bool ExtractLogicallyNegatedTerm(minsn_t *ins, minsn_t *&insNegated, mop_t **opN if (ins->opcode == m_lnot) { // Extract the operand, if requested by the caller. - if(opNegated != NULL) + if(opNegated != nullptr) *opNegated = &ins->l; // If the operand was mop_d (i.e., result of another microinstruction), @@ -149,8 +149,8 @@ bool ExtractLogicallyNegatedTerm(minsn_t *ins, minsn_t *&insNegated, mop_t **opN // on whether the caller was willing to accept a non-mop_d operand. else { - insNegated = NULL; - return opNegated != NULL; + insNegated = nullptr; + return opNegated != nullptr; } } @@ -172,7 +172,7 @@ bool ExtractLogicallyNegatedTerm(minsn_t *ins, minsn_t *&insNegated, mop_t **opN return false; // If the caller wanted an operand, give it to them. - if (opNegated != NULL) + if (opNegated != nullptr) *opNegated = xorNonNum; // If the operand was mop_d (result of another microinstruction), extract @@ -186,8 +186,8 @@ bool ExtractLogicallyNegatedTerm(minsn_t *ins, minsn_t *&insNegated, mop_t **opN // Otherwise, if the operand was not of type mop_d, "success" depends on // whether the caller was willing to accept a non-mop_d operand. - insNegated = NULL; - return opNegated != NULL; + insNegated = nullptr; + return opNegated != nullptr; } // This function checks whether two conditional terms are logically opposite. @@ -209,7 +209,7 @@ bool AreConditionsOpposite(minsn_t *lhsCond, minsn_t *rhsCond) // lhsCond and rhsCond will be set to NULL if their original terms were // negated, but the thing that was negated wasn't the result of another // microinstruction. - if (lhsCond == NULL || rhsCond == NULL) + if (lhsCond == nullptr || rhsCond == nullptr) return false; // If one was negated and the other wasn't, compare them for equality. diff --git a/PatternDeobfuscateUtil.hpp b/PatternDeobfuscateUtil.hpp index f6bfb33..c8cd276 100644 --- a/PatternDeobfuscateUtil.hpp +++ b/PatternDeobfuscateUtil.hpp @@ -4,9 +4,9 @@ bool ExtractNumAndNonNum(minsn_t *insn, mop_t *&numOp, mop_t *&otherOp); bool ExtractByOpcodeType(minsn_t *ins, mcode_t mc, minsn_t *&match, mop_t*& noMatch); -bool TunnelThroughAnd1(minsn_t *ins, minsn_t *&inner, bool bRequireSize1 = true, mop_t **opInner = NULL); +bool TunnelThroughAnd1(minsn_t *ins, minsn_t *&inner, bool bRequireSize1 = true, mop_t **opInner = nullptr); bool AreConditionCodesOpposite(mcode_t c1, mcode_t c2); -bool ExtractLogicallyNegatedTerm(minsn_t *ins, minsn_t *&insNegated, mop_t **opNegated = NULL); +bool ExtractLogicallyNegatedTerm(minsn_t *ins, minsn_t *&insNegated, mop_t **opNegated = nullptr); bool AreConditionsOpposite(minsn_t *lhsCond, minsn_t *rhsCond); class XorSimplifier diff --git a/PropertySheet.props b/PropertySheet.props new file mode 100644 index 0000000..b78cbfd --- /dev/null +++ b/PropertySheet.props @@ -0,0 +1,20 @@ + + + + + C:\progra~1\ida 7.5 + C:\progra~1\ida 7.5\idasdk75 + + + + + + $(IDADIR) + true + + + $(IDASDK) + true + + + diff --git a/TargetUtil.cpp b/TargetUtil.cpp index 9ea5eac..6d425d3 100644 --- a/TargetUtil.cpp +++ b/TargetUtil.cpp @@ -54,7 +54,7 @@ void ChangeSingleTarget(mblock_t *blk, int iOldTarget, int iNewTarget) // this block end in a call instruction? bool is_call_block(mblock_t *blk) { - if (blk->tail == NULL) + if (blk->tail == nullptr) return false; return blk->tail->opcode == m_call || blk->tail->opcode == m_icall; @@ -86,7 +86,7 @@ int RemoveSingleGotos(mbl_array_t *mba) minsn_t *m2 = getf_reginsn(b->head); // Is the first non-assert instruction a goto? - if (m2 == NULL || m2->opcode != m_goto) + if (m2 == nullptr || m2->opcode != m_goto) continue; // If it was a goto, record the destination block number @@ -107,7 +107,7 @@ int RemoveSingleGotos(mbl_array_t *mba) // Get the last instruction on the block minsn_t *mgoto = blk->tail; - if (mgoto == NULL) + if (mgoto == nullptr) continue; int iOriginalGotoTarget; @@ -216,9 +216,9 @@ bool ExtractJccParts(mblock_t *pred1, mblock_t *&endsWithJcc, int &jccDest, int // that doesn't. Also return the integer numbers of those blocks. bool SplitMblocksByJccEnding(mblock_t *pred1, mblock_t *pred2, mblock_t *&endsWithJcc, mblock_t *&nonJcc, int &jccDest, int &jccFallthrough) { - endsWithJcc = NULL; - nonJcc = NULL; - if (pred1->tail == NULL || pred2->tail == NULL) + endsWithJcc = nullptr; + nonJcc = nullptr; + if (pred1->tail == nullptr || pred2->tail == nullptr) return false; // Check if the first block ends with jcc. Make sure the second one @@ -348,8 +348,8 @@ void DeleteBlock(mblock_t *mb) mb->succset.del(mb->succ(0)); // Delete the instructions on the block - minsn_t *pCurr = mb->head, *pNext = NULL; - while (pCurr != NULL) + minsn_t *pCurr = mb->head, *pNext = nullptr; + while (pCurr != nullptr) { pNext = pCurr->next; delete pCurr; @@ -357,8 +357,8 @@ void DeleteBlock(mblock_t *mb) } // Mark that the block now has no instructions. - mb->head = NULL; - mb->tail = NULL; + mb->head = nullptr; + mb->tail = nullptr; } // The goto-to-goto elimination and unflattening phases remove edges in the diff --git a/Unflattener.cpp b/Unflattener.cpp index 42eb756..8cb945b 100644 --- a/Unflattener.cpp +++ b/Unflattener.cpp @@ -3,7 +3,6 @@ #define USE_DANGEROUS_FUNCTIONS #include -#include "HexRaysUtil.hpp" #include "Unflattener.hpp" #include "CFFlattenInfo.hpp" #include "TargetUtil.hpp" @@ -39,7 +38,7 @@ int atThisMaturity = 0; // the control flow flattening switch. mblock_t *CFUnflattener::GetDominatedClusterHead(mbl_array_t *mba, int iDispPred, int &iClusterHead) { - mblock_t *mbClusterHead = NULL; + mblock_t *mbClusterHead = nullptr; // Find the block that is targeted by the dispatcher, and that // dominates the block we're currently looking at. This logic won't // work for the first block (since it wasn't targeted by the control @@ -55,7 +54,7 @@ mblock_t *CFUnflattener::GetDominatedClusterHead(mbl_array_t *mba, int iDispPred if (iClusterHead < 0) { debugmsg("[I] Block %d was not part of a dominated cluster\n", iDispPred); - return NULL; + return nullptr; } mbClusterHead = mba->get_mblock(iClusterHead); #if UNFLATTENVERBOSE @@ -86,7 +85,7 @@ int CFUnflattener::FindBlockTargetOrLastCopy(mblock_t *mb, mblock_t *mbClusterHe MovChain local; - mop_t *opNum = NULL, *opCopy; + mop_t *opNum = nullptr, *opCopy; // Search backwards looking for a numeric assignment to "what". We may or // may not find a numeric assignment, but we might find intervening // assignments where "what" is copied from other variables. @@ -111,7 +110,7 @@ int CFUnflattener::FindBlockTargetOrLastCopy(mblock_t *mb, mblock_t *mbClusterHe // of the cluster. If we don't find it, this is not necessarily an // indication that the analysis failed; for blocks with two successors, // we do further analysis. - if (!bFound && opCopy != NULL && opCopy->t == mop_S) + if (!bFound && opCopy != nullptr && opCopy->t == mop_S) { mop_t *num = FindForwardStackVarDef(mbClusterHead, opCopy, local); if (num) @@ -163,9 +162,9 @@ bool CFUnflattener::HandleTwoPreds(mblock_t *mb, mblock_t *mbClusterHead, mop_t mblock_t *pred1 = mba->get_mblock(mb->pred(0)); mblock_t *pred2 = mba->get_mblock(mb->pred(1)); - mblock_t *endsWithJcc = NULL; - nonJcc = NULL; - int jccDest = -1, jccFallthrough = -1; + mblock_t *endsWithJcc = nullptr; + nonJcc = nullptr; + int jccDest = -1, jccFallthrough = -1; // Given the two predecessors, find the block with the conditional jump at // the end of it (store the block in "endsWithJcc") and the one without @@ -336,7 +335,7 @@ int idaapi CFUnflattener::func(mblock_t *blk) // definitions. int iClusterHead; mblock_t *mbClusterHead = GetDominatedClusterHead(mba, iDispPred, iClusterHead); - if (mbClusterHead == NULL) + if (mbClusterHead == nullptr) continue; // It's best to process erasures for every block we unflatten @@ -432,7 +431,7 @@ int idaapi CFUnflattener::func(mblock_t *blk) debugmsg("[I] %d: tail is %s\n", nonJcc->serial, buf); #endif - } while (mbCurr != NULL); + } while (mbCurr != nullptr); // Make a note to ourselves to modify the graph structure later, diff --git a/Unflattener.hpp b/Unflattener.hpp index 9abc313..f6d88df 100644 --- a/Unflattener.hpp +++ b/Unflattener.hpp @@ -1,10 +1,9 @@ #pragma once -#include #include #include "CFFlattenInfo.hpp" #include "DefUtil.hpp" -struct CFUnflattener : public optblock_t +struct CFUnflattener : optblock_t { CFFlattenInfo cfi; MovChain m_DeferredErasuresLocal; diff --git a/bin/IDA75_32/HexRaysDeob.dll b/bin/IDA75_32/HexRaysDeob.dll new file mode 100755 index 0000000..2ac6038 Binary files /dev/null and b/bin/IDA75_32/HexRaysDeob.dll differ diff --git a/bin/IDA75_64/HexRaysDeob.dll b/bin/IDA75_64/HexRaysDeob.dll new file mode 100755 index 0000000..f72ea58 Binary files /dev/null and b/bin/IDA75_64/HexRaysDeob.dll differ diff --git a/main.cpp b/main.cpp index cfdc8a0..a73ac0f 100644 --- a/main.cpp +++ b/main.cpp @@ -10,7 +10,6 @@ #include #define USE_DANGEROUS_FUNCTIONS #include -#include "HexRaysUtil.hpp" #include "MicrocodeExplorer.hpp" #include "PatternDeobfuscate.hpp" #include "AllocaFixer.hpp" @@ -20,13 +19,18 @@ extern plugin_t PLUGIN; // Hex-Rays API pointer -hexdsp_t *hexdsp = NULL; +hexdsp_t *hexdsp = nullptr; ObfCompilerOptimizer hook; CFUnflattener cfu; //-------------------------------------------------------------------------- + +#if IDA_SDK_VERSION <= 730 int idaapi init(void) +#else +plugmod_t* idaapi init() ///< Initialize plugin - returns a pointer to plugmod_t +#endif { if (!init_hexrays_plugin()) return PLUGIN_SKIP; // no decompiler @@ -44,7 +48,7 @@ int idaapi init(void) //-------------------------------------------------------------------------- void idaapi term(void) { - if (hexdsp != NULL) + if (hexdsp != nullptr) { // Uninstall our block and instruction optimization classes.