// // Copyright © 20.02.04 Dmitry Friesen // ///////////////////////////////////////// // Check and create fragmented function // Version: 1.5 // // Sample: MSVBVM05.dll or MSVBVM60.dll ///////////////////////////////////////// // // 24.02.04 Add: Parse - switch () {case:...}; // 24.02.04 Add: Set first ESP for fragment // ///////////////////////////////////////// #include // IDA Message(...) for double-clickind in "Output Window"! static MyMessage(ea, msg) { Message("%s:%08X: %s", SegName(ea), ea, msg); } // Add ea to "Sorted Address List" static AddAddr(ea) { auto id, idx, val; if ( (id = GetArrayId("AddrList")) == -1 ) { id = CreateArray("AddrList"); SetArrayLong(id, 0, ea); return; } for ( idx = GetFirstIndex(AR_LONG, id); idx != -1; idx = GetNextIndex(AR_LONG, id, idx) ) { val = GetArrayElement(AR_LONG, id, idx); if ( val == ea ) return; if ( val > ea ) // InSort { for ( ; idx != -1; idx = GetNextIndex(AR_LONG, id, idx) ) { val = GetArrayElement(AR_LONG, id, idx); SetArrayLong(id, idx, ea); ea = val; } } } SetArrayLong(id, GetLastIndex(AR_LONG, id) + 1, ea); } static ParseSwitch(ea, startEA, endEA) { auto mnem, op0, swcEA, op1, caseEA, nCase, maxCase; mnem = GetMnem(ea); op0 = GetOpnd(ea, 0); swcEA = LocByName(substr(op0, 3, strstr(op0 , "["))); ea = PrevHead(ea, startEA); maxCase = -1; if ( ea != BADADDR ) { if ( strstr(GetMnem(ea), "mov") == 0 ) { op1 = GetOpnd(ea, 1); if ( strstr(op1, "ds:") == 0 && strstr(op1, "[") != -1 ) { caseEA = LocByName(substr(op1, 3, strstr(op1 , "["))); if ( caseEA != BADADDR ) { while ( (ea = PrevHead(ea, startEA)) != BADADDR ) { if ( GetMnem(ea) == "cmp" ) { nCase = GetOperandValue(ea, 1); while ( nCase-- >= 0 ) { if ( Byte(caseEA) > maxCase ) maxCase = Byte(caseEA); caseEA++; } } } } } } else if ( strstr(GetMnem(ea), "j") == 0 ) { while ( (ea = PrevHead(ea, startEA)) != BADADDR ) { if ( GetMnem(ea) == "cmp" ) { if ( strstr(GetOpnd(ea, 1), "e") == 0 ) break; maxCase = GetOperandValue(ea, 1); break; } } } } if ( maxCase != -1 ) { for ( ea = swcEA; maxCase >= 0; ea = ea + 4 ) { if ( Dword(ea) > endEA ) AddAddr(Dword(ea)); maxCase--; } return; } MyMessage(ea, form(" ---> ERROR: Illegal switch '%s %s' command at %08X!\n", mnem, op0, swcEA)); } // Analyse and Make Fragment for function static AnalyseFunc(startEA, endEA) { auto fncName, mnem, jmpEA, op0; auto ea, id, idx; auto startFR, endFR; auto local, saved, args; fncName = GetFunctionName(startEA); local = GetFrameLvarSize(startEA); saved = GetFrameRegsSize(startEA); args = GetFrameArgsSize(startEA); MyMessage(startEA, form("Looking fragment's for '%s', end address is %08X\n", fncName, endEA)); // Looking-for fragment entries for ( ea = startEA; ea != BADADDR && ea < endEA; ea = NextHead(ea, BADADDR) ) { mnem = GetMnem(ea); if ( strstr(mnem, "j") == 0 ) { op0 = GetOpnd(ea, 0); if ( strstr(op0 , "ds:") == 0 && strstr(op0 , "[") != -1 ) ParseSwitch(ea, startEA, endEA); else if ( (jmpEA = LocByName(op0)) != BADADDR ) { if ( jmpEA > endEA ) AddAddr(jmpEA); } else MyMessage(ea, form(" ---> ERROR: Illegal '%s %s' command!\n", mnem, GetOpnd(ea, 0))); } } // Create function fragment if ( (id = GetArrayId("AddrList")) == -1 ) { MyMessage(startEA, form("Not found fragment for '%s'\n", fncName)); return; } idx = GetFirstIndex(AR_LONG, id); if ( idx == -1 ) { MyMessage(startEA, form("Not found fragment for '%s'\n", fncName)); return; } ea = GetArrayElement(AR_LONG, id, idx); startFR = ea; MyMessage(startFR, " <--- Fragment start\n"); if ( GetFunctionName(ea) == "" ) { if ( MakeFunction(ea, BADADDR) == 0 ) { MyMessage(ea, " ---> ERROR: MakeFunction(ea, BADADDR)!\n"); return; } } if ( (endFR = FindFuncEnd(ea)) == BADADDR ) { MyMessage(ea, " ---> ERROR: Function end cannot be determined!\n"); return; } MakeName(startFR, form("frm_%s", fncName)); SetFunctionCmt(startFR, form("The fragment of %s", fncName), 0); SetFunctionFlags(startFR, GetFunctionFlags(startEA)); SetSpDiff(startFR, GetSpd(RfirstB(ea)) - GetSpDiff(startFR)); while ( (idx = GetNextIndex(AR_LONG, id, idx)) != -1 ) { ea = GetArrayElement(AR_LONG, id, idx); if ( ea == endFR ) { if ( GetFunctionName(ea) == "" ) { if ( MakeFunction(ea, BADADDR) == 0 ) { MyMessage(ea, " ---> ERROR: MakeFunction(ea, BADADDR)!\n"); return; } } if ( (endFR = FindFuncEnd(ea)) == BADADDR ) { MyMessage(ea, " ---> ERROR: Function end cannot be determined!\n"); return; } if ( DelFunction(ea) == 0 ) { MyMessage(ea, " ---> ERROR: DelFunction(ea)!\n"); return; } if ( SetFunctionEnd(startFR, endFR) == 0 ) { MyMessage(endFR, " ---> ERROR: SetFunctionEnd(startFR, endFR)!\n"); return; } } else if ( ea > endFR ) { // TODO: ???? MyMessage(ea, form(" ---> ERROR: Hole at %08X!\n", endFR)); return; } MakeRptCmt(ea, "-> to fragment"); // TODO: SetESP(ea, value); } if ( local < GetFrameLvarSize(startFR) ) local = GetFrameLvarSize(startFR); if ( saved < GetFrameRegsSize(startFR) ) saved = GetFrameRegsSize(startFR); if ( args < GetFrameArgsSize(startFR) ) args = GetFrameArgsSize(startFR); MakeFrame(startEA, local, saved, args); MakeFrame(startFR, local, saved, args); // TODO: Synchronize local variable's MyMessage(endFR, " <--- Fragment end\n"); } // Main Entry static main() { auto ea, end, str, id; // // Make fragmented function: // ea = ScreenEA(); if ( (str = GetFuncOffset(ea)) == 0 ) return; if ( (id = strstr(str, "+")) != -1 ) ea = ea - xtol(substr(str, id + 1, -1)); if ( (end = FindFuncEnd(ea)) == BADADDR ) { MyMessage(ea, " ---> ERROR: Function end cannot be determined!\n"); return; } AnalyseFunc(ea, end); if ( (id = GetArrayId("AddrList")) != -1 ) { DeleteArray(id); } }