//--------------------------------------------------------------------------- void __fastcall TFMain_11011981::lbUnitItemsDblClick(TObject *Sender) { int idx = -1, len, size, refCnt; WORD* uses; DWORD adr; char *tmpBuf; PInfoRec recN; MTypeInfo tInfo; String str; char tkName[32], typeName[1024]; if (lbUnitItems->ItemIndex == -1) return; String item = lbUnitItems->Items->Strings[lbUnitItems->ItemIndex]; //Xrefs? if (item[11] == '<' || item[11] == '?') sscanf(item.c_str() + 1, "%lX%s%s", &adr, tkName, typeName); else sscanf(item.c_str() + 1, "%lX%d%s%s", &adr, &refCnt, tkName, typeName); String name = String(tkName); if (SameText(name, "????")) { //Find end of unexplored Data int bytes = 1024, pos = Adr2Pos(adr); //Get first byte (use later for filtering code?data) BYTE db = *(Code + pos); FExplorer_11011981->tsCode->TabVisible = true; FExplorer_11011981->ShowCode(adr, bytes); FExplorer_11011981->tsData->TabVisible = true; FExplorer_11011981->ShowData(adr, bytes); FExplorer_11011981->tsString->TabVisible = true; FExplorer_11011981->ShowString(adr, 1024); FExplorer_11011981->tsText->TabVisible = false; FExplorer_11011981->WAlign = 0; FExplorer_11011981->btnDefCode->Enabled = true; if (IsFlagSet(cfCode, pos)) FExplorer_11011981->btnDefCode->Enabled = false; FExplorer_11011981->btnUndefCode->Enabled = false; if (IsFlagSet(cfCode | cfData, pos)) FExplorer_11011981->btnUndefCode->Enabled = true; if (IsValidCode(adr) != -1 && db >= 0xF) FExplorer_11011981->pc1->ActivePage = FExplorer_11011981->tsCode; else FExplorer_11011981->pc1->ActivePage = FExplorer_11011981->tsData; if (FExplorer_11011981->ShowModal() == mrOk) { switch (FExplorer_11011981->DefineAs) { case DEFINE_AS_CODE: recN = GetInfoRec(adr); if (!recN) recN = new InfoRec(pos, ikRefine); else if (recN->kind < ikRefine || recN->kind > ikFunc) { delete recN; recN = new InfoRec(pos, ikRefine); } //AnalyzeProcInitial(adr); AnalyzeProc1(adr, 0, 0, 0, false); AnalyzeProc2(adr, true, true); AnalyzeArguments(adr); AnalyzeProc2(adr, true, true); if (!ContainsUnexplored(GetUnit(adr))) ShowUnits(true); ShowUnitItems(GetUnit(adr), lbUnitItems->TopIndex, lbUnitItems->ItemIndex); ShowCode(adr, 0, -1, -1); break; case DEFINE_AS_STRING: break; } } return; } if (SameText(name, "<VMT>") && tsClassView->TabVisible) { ShowClassViewer(adr); return; } if (SameText(name, "<ResString>")) { FStringInfo_11011981->memStringInfo->Clear(); FStringInfo_11011981->Caption = "ResString"; recN = GetInfoRec(adr); FStringInfo_11011981->memStringInfo->Lines->Add(recN->rsInfo->value); FStringInfo_11011981->ShowModal(); return; } if (SameText(name, "<ShortString>") || SameText(name, "<AnsiString>") || SameText(name, "<WideString>") || SameText(name, "<PAnsiChar>") || SameText(name, "<PWideChar>")) { FStringInfo_11011981->memStringInfo->Clear(); FStringInfo_11011981->Caption = "String"; recN = GetInfoRec(adr); FStringInfo_11011981->memStringInfo->Lines->Add(recN->GetName()); FStringInfo_11011981->ShowModal(); return; } if (SameText(name, "<UString>")) { FStringInfo_11011981->memStringInfo->Clear(); FStringInfo_11011981->Caption = "String"; recN = GetInfoRec(adr); len = wcslen((wchar_t*)(Code + Adr2Pos(adr))); size = WideCharToMultiByte(CP_ACP, 0, (wchar_t*)(Code + Adr2Pos(adr)), len, 0, 0, 0, 0); if (size) { tmpBuf = new char[size + 1]; WideCharToMultiByte(CP_ACP, 0, (wchar_t*)(Code + Adr2Pos(adr)), len, tmpBuf, len, 0, 0); FStringInfo_11011981->memStringInfo->Lines->Add(String(tmpBuf, len)); delete[] tmpBuf; FStringInfo_11011981->ShowModal(); } return; } if (SameText(name, "<Integer>") || SameText(name, "<Char>") || SameText(name, "<Enumeration>") || SameText(name, "<Float>") || SameText(name, "<Set>") || SameText(name, "<Class>") || SameText(name, "<Method>") || SameText(name, "<WChar>") || SameText(name, "<Array>") || SameText(name, "<Record>") || SameText(name, "<Interface>") || SameText(name, "<Int64>") || SameText(name, "<DynArray>") || SameText(name, "<ClassRef>") || SameText(name, "<Pointer>") || SameText(name, "<Procedure>")) { uses = KnowledgeBase.GetTypeUses(typeName); idx = KnowledgeBase.GetTypeIdxByModuleIds(uses, typeName); if (uses) delete[] uses; if (idx != -1) { idx = KnowledgeBase.TypeOffsets[idx].NamId; if (KnowledgeBase.GetTypeInfo(idx, INFO_FIELDS | INFO_PROPS | INFO_METHODS, &tInfo)) { FTypeInfo_11011981->ShowKbInfo(&tInfo); //as delete tInfo; } } else { FTypeInfo_11011981->ShowRTTI(adr); } return; } if (SameText(name, "<Proc>") || SameText(name, "<Func>") || SameText(name, "<Constructor>") || SameText(name, "<Destructor>") || SameText(name, "<EmbProc>") || SameText(name, "<EmbFunc>") || SameText(name, "<Emb?>") || SameText(name, "<ImpProc>") || SameText(name, "<ExpProc>") || SameText(name, "<ImpFunc>") || SameText(name, "<ExpFunc>") || SameText(name, "<Imp?>") || SameText(name, "<Exp?>") || SameText(name, "<?>")) { PROCHISTORYREC rec; rec.adr = CurProcAdr; rec.itemIdx = lbCode->ItemIndex; rec.xrefIdx = lbCXrefs->ItemIndex; rec.topIdx = lbCode->TopIndex; ShowCode(adr, 0, -1, -1); CodeHistoryPush(&rec); pcWorkArea->ActivePage = tsCodeView; } }
//--------------------------------------------------------------------------- String __fastcall TFMain_11011981::AnalyzeArguments(DWORD fromAdr) { BYTE op; bool kb; bool bpBased; bool emb, lastemb; bool argA, argD, argC; bool inA, inD, inC; bool spRestored = false; WORD bpBase, retBytes; int num, instrLen, instrLen1, instrLen2, _procSize; int firstPopRegIdx = -1, popBytes = 0, procStackSize = 0; int fromPos, curPos, Pos, reg1Idx, reg2Idx, sSize; DWORD b, curAdr, Adr, Adr1; DWORD lastAdr = 0, lastCallAdr = 0, lastMovAdr = 0, lastMovImm = 0; PInfoRec recN, recN1; PARGINFO argInfo; DWORD stack[256]; int sp = -1; int macroFrom, macroTo; String minClassName, className = "", retType = ""; DISINFO DisInfo, DisInfo1; fromPos = Adr2Pos(fromAdr); if (fromPos < 0) return ""; if (IsFlagSet(cfEmbedded, fromPos)) return ""; if (IsFlagSet(cfExport, fromPos)) return ""; recN = GetInfoRec(fromAdr); if (!recN || !recN->procInfo) return ""; //If cfPass is set exit if (IsFlagSet(cfPass, fromPos)) return recN->type; //Proc start SetFlag(cfProcStart | cfPass, fromPos); //Skip Imports if (IsFlagSet(cfImport, fromPos)) return recN->type; kb = (recN->procInfo->flags & PF_KBPROTO); bpBased = (recN->procInfo->flags & PF_BPBASED); emb = (recN->procInfo->flags & PF_EMBED); bpBase = recN->procInfo->bpBase; retBytes = recN->procInfo->retBytes; //If constructor or destructor get class name if (recN->kind == ikConstructor || recN->kind == ikDestructor) className = ExtractClassName(recN->GetName()); //If ClassName not given and proc is dynamic, try to find minimal class if (className == "" && (recN->procInfo->flags & PF_DYNAMIC) && recN->xrefs) { minClassName = ""; for (int n = 0; n < recN->xrefs->Count; n++) { PXrefRec recX = (PXrefRec)recN->xrefs->Items[n]; if (recX->type == 'D') { className = GetClsName(recX->adr); if (minClassName == "" || !IsInheritsByClassName(className, minClassName)) minClassName = className; } } if (minClassName != "") className = minClassName; } //If ClassName not given and proc is virtual, try to find minimal class if (className == "" && (recN->procInfo->flags & PF_VIRTUAL) && recN->xrefs) { minClassName = ""; for (int n = 0; n < recN->xrefs->Count; n++) { PXrefRec recX = (PXrefRec)recN->xrefs->Items[n]; if (recX->type == 'D') { className = GetClsName(recX->adr); if (minClassName == "" || !IsInheritsByClassName(className, minClassName)) minClassName = className; } } if (minClassName != "") className = minClassName; } argA = argD = argC = true; //On entry inA = inD = inC = false; //No arguments _procSize = GetProcSize(fromAdr); curPos = fromPos; curAdr = fromAdr; while (1) { if (curAdr >= CodeBase + TotalSize) break; //Skip exception table if (IsFlagSet(cfETable, curPos)) { //dd num num = *((int*)(Code + curPos)); curPos += 4 + 8*num; curAdr += 4 + 8*num; continue; } BYTE b1 = Code[curPos]; BYTE b2 = Code[curPos + 1]; instrLen = Disasm.Disassemble(Code + curPos, (__int64)curAdr, &DisInfo, 0); //if (!instrLen) break; if (!instrLen) { curPos++; curAdr++; continue; } op = Disasm.GetOp(DisInfo.Mnem); //Code SetFlags(cfCode, curPos, instrLen); //Instruction begin SetFlag(cfInstruction, curPos); if (curAdr >= lastAdr) lastAdr = 0; if (op == OP_JMP) { if (curAdr == fromAdr) break; if (DisInfo.OpType[0] == otMEM) { if (Adr2Pos(DisInfo.Offset) < 0 && (!lastAdr || curAdr == lastAdr)) break; } if (DisInfo.OpType[0] == otIMM) { Adr = DisInfo.Immediate; if (Adr2Pos(Adr) < 0 && (!lastAdr || curAdr == lastAdr)) break; if (GetSegmentNo(Adr) != 0 && GetSegmentNo(fromAdr) != GetSegmentNo(Adr) && (!lastAdr || curAdr == lastAdr)) break; if (Adr < fromAdr && (!lastAdr || curAdr == lastAdr)) break; curPos += instrLen; curAdr += instrLen; continue; } } if (DisInfo.Ret) { //End of proc if (!lastAdr || curAdr == lastAdr) { //Get last instruction curPos -= instrLen; if ((DisInfo.Ret && !IsFlagSet(cfSkip, curPos)) || //ret not in SEH IsFlagSet(cfCall, curPos)) //@Halt0 { if (IsFlagSet(cfCall, curPos)) spRestored = true; //acts like mov esp, ebp sp = -1; SetFlags(cfFrame, curPos, instrLen); //ret - stop analyze output regs lastCallAdr = 0; firstPopRegIdx = -1; popBytes = 0; //define all pop registers (ret skipped) for (Pos = curPos - 1; Pos >= fromPos; Pos--) { b = Flags[Pos]; if (b & cfInstruction) { //pop instruction if (b & cfPop) { //pop ecx if (b & cfSkip) break; instrLen1 = Disasm.Disassemble(Code + Pos, (__int64)Pos2Adr(Pos), &DisInfo1, 0); firstPopRegIdx = DisInfo1.OpRegIdx[0]; popBytes += 4; SetFlags(cfFrame, Pos, instrLen1); } else { //skip frame instruction if (b & cfFrame) continue; //set eax - function if (b & cfSetA) { recN1 = GetInfoRec(fromAdr); recN1->procInfo->flags |= PF_OUTEAX; if (!kb && !(recN1->procInfo->flags & (PF_EVENT | PF_DYNAMIC)) && recN1->kind != ikConstructor && recN1->kind != ikDestructor) { recN1->kind = ikFunc; Disasm.Disassemble(Code + Pos, (__int64)Pos2Adr(Pos), &DisInfo1, 0); op = Disasm.GetOp(DisInfo1.Mnem); //if setXX - return type is Boolean if (op == OP_SET) recN1->type = "Boolean"; } } break; } } } } if (firstPopRegIdx!= -1) { //Skip pushed regs if (spRestored) { for (Pos = fromPos;;Pos++) { b = Flags[Pos]; //Proc end //if (Pos != fromPos && (b & cfProcEnd)) if (_procSize && Pos - fromPos + 1 >= _procSize) break; if (b & cfInstruction) { instrLen1 = Disasm.Disassemble(Code + Pos, (__int64)Pos2Adr(Pos), &DisInfo1, 0); SetFlags(cfFrame, Pos, instrLen1); if ((b & cfPush) && (DisInfo1.OpRegIdx[0] == firstPopRegIdx)) break; } } } else { for (Pos = fromPos;;Pos++) { if (!popBytes) break; b = Flags[Pos]; //End of proc //if (Pos != fromPos && (b & cfProcEnd)) if (_procSize && Pos - fromPos + 1 >= _procSize) break; if (b & cfInstruction) { instrLen1 = Disasm.Disassemble(Code + Pos, (__int64)Pos2Adr(Pos), &DisInfo1, 0); op = Disasm.GetOp(DisInfo1.Mnem); SetFlags(cfFrame, Pos, instrLen1); //add esp,... if (op == OP_ADD && DisInfo1.OpRegIdx[0] == 20) { popBytes += (int)DisInfo1.Immediate; continue; } //sub esp,... if (op == OP_SUB && DisInfo1.OpRegIdx[0] == 20) { popBytes -= (int)DisInfo1.Immediate; continue; } if (b & cfPush) popBytes -= 4; } } } } //If no prototype, try add information from analyze arguments result if (!recN->HasName() && className != "") { //dynamic if (recN->procInfo->flags & PF_DYNAMIC) { } else { } } if (!kb) { if (inA) { if (className != "") recN->procInfo->AddArg(0x21, 0, 4, "Self", className); else recN->procInfo->AddArg(0x21, 0, 4, "", ""); } if (inD) { if (recN->kind == ikConstructor || recN->kind == ikDestructor) recN->procInfo->AddArg(0x21, 1, 4, "_Dv__", "Boolean"); else recN->procInfo->AddArg(0x21, 1, 4, "", ""); } if (inC) { recN->procInfo->AddArg(0x21, 2, 4, "", ""); } } break; } if (!IsFlagSet(cfSkip, curPos)) sp = -1; } if (op == OP_MOV) { lastMovAdr = DisInfo.Offset; lastMovImm = DisInfo.Immediate; } //init stack via loop if (IsFlagSet(cfLoc, curPos)) { recN1 = GetInfoRec(curAdr); if (recN1 && recN1->xrefs && recN1->xrefs->Count == 1) { PXrefRec recX = (PXrefRec)recN1->xrefs->Items[0]; Adr = recX->adr + recX->offset; if (Adr > curAdr) { sSize = IsInitStackViaLoop(curAdr, Adr); if (sSize) { procStackSize += sSize * lastMovImm; //skip jne instrLen = Disasm.Disassemble(Code + Adr2Pos(Adr), (__int64)Adr, 0, 0); curAdr = Adr + instrLen; curPos = Adr2Pos(curAdr); SetFlags(cfFrame, fromPos, curAdr - fromAdr); continue; } } } } //add (sub) esp,... if (DisInfo.OpRegIdx[0] == 20 && DisInfo.OpType[1] == otIMM) { if (op == OP_ADD) { if ((int)DisInfo.Immediate < 0) procStackSize -= (int)DisInfo.Immediate; } if (op == OP_SUB) { if ((int)DisInfo.Immediate > 0) procStackSize += (int)DisInfo.Immediate; } curPos += instrLen; curAdr += instrLen; continue; } /* //dec reg if (op == OP_DEC && DisInfo.Op1Type == otREG) { //Save (dec reg) address Adr = curAdr; //Look next instruction curPos += instrLen; curAdr += instrLen; instrLen = Disasm.Disassemble(Code + curPos, (__int64)curAdr, &DisInfo1, 0); //If jne @1, where @1 < adr of jne, when make frame from begin if Stack inited via loop if (DisInfo1.Conditional && DisInfo1.Immediate < curAdr && DisInfo1.Immediate >= fromAdr) { if (IsInitStackViaLoop(DisInfo1.Immediate, Adr)) SetFlags(cfFrame, fromPos, curPos + instrLen - fromPos + 1); } continue; } */ //mov esp, ebp if (b1 == 0x8B && b2 == 0xE5) spRestored = true; if (!IsFlagSet(cfSkip, curPos)) { if (IsFlagSet(cfPush, curPos)) { if (curPos != fromPos && sp < 255) { sp++; stack[sp] = curPos; } } if (IsFlagSet(cfPop, curPos) && sp >= 0) { macroFrom = stack[sp]; SetFlag(cfBracket, macroFrom); macroTo = curPos; SetFlag(cfBracket, macroTo); sp--; } } if (b1 == 0xFF && (b2 & 0x38) == 0x20 && DisInfo.OpType[0] == otMEM && IsValidImageAdr(DisInfo.Offset)) //near absolute indirect jmp (Case) { if (!IsValidCodeAdr(DisInfo.Offset)) break; DWORD cTblAdr = 0, jTblAdr = 0; Pos = curPos + instrLen; Adr = curAdr + instrLen; //Taqble address - last 4 bytes of instruction jTblAdr = *((DWORD*)(Code + Pos - 4)); //Analyze gap to find table cTbl if (Adr <= lastMovAdr && lastMovAdr < jTblAdr) cTblAdr = lastMovAdr; //If cTblAdr exists, skip it BYTE CTab[256]; if (cTblAdr) { int CNum = jTblAdr - cTblAdr; Pos += CNum; Adr += CNum; } for (int k = 0; k < 4096; k++) { //Loc - end of table if (IsFlagSet(cfLoc, Pos)) break; Adr1 = *((DWORD*)(Code + Pos)); //Validate Adr1 if (!IsValidCodeAdr(Adr1) || Adr1 < fromAdr) break; //Set cfLoc SetFlag(cfLoc, Adr2Pos(Adr1)); Pos += 4; Adr += 4; if (Adr1 > lastAdr) lastAdr = Adr1; } if (Adr > lastAdr) lastAdr = Adr; curPos = Pos; curAdr = Adr; continue; } //---------------------------------- //PosTry: xor reg, reg // push ebp // push offset @1 // push fs:[reg] // mov fs:[reg], esp // ... //@2: ... //At @1 we have various situations: //---------------------------------- //@1: jmp @HandleFinally // jmp @2 //---------------------------------- //@1: jmp @HandleAnyException // call DoneExcept //---------------------------------- //@1: jmp HandleOnException // dd num //Follow the table of num records like: // dd offset ExceptionInfo // dd offset ExceptionProc //---------------------------------- if (b1 == 0x68) //try block (push loc_TryBeg) { DWORD NPos = curPos + instrLen; //check that next instruction is push fs:[reg] or retn if ((Code[NPos] == 0x64 && Code[NPos + 1] == 0xFF && ((Code[NPos + 2] >= 0x30 && Code[NPos + 2] <= 0x37) || Code[NPos + 2] == 0x75)) || Code[NPos] == 0xC3) { Adr = DisInfo.Immediate; //Adr=@1 if (IsValidCodeAdr(Adr)) { if (Adr > lastAdr) lastAdr = Adr; Pos = Adr2Pos(Adr); if (Pos >= 0 && Pos - NPos < MAX_DISASSEMBLE) { if (Code[Pos] == 0xE9) //jmp Handle... { //Disassemble jmp instrLen1 = Disasm.Disassemble(Code + Pos, (__int64)Adr, &DisInfo, 0); recN1 = GetInfoRec(DisInfo.Immediate); if (recN1) { if (recN1->SameName("@HandleFinally")) { //ret + jmp HandleFinally Pos += instrLen1; Adr += instrLen1; //jmp @2 instrLen2 = Disasm.Disassemble(Code + Pos, (__int64)Adr, &DisInfo, 0); Adr += instrLen2; if (Adr > lastAdr) lastAdr = Adr; } else if (recN1->SameName("@HandleAnyException") || recN1->SameName("@HandleAutoException")) { //jmp HandleAnyException Pos += instrLen1; Adr += instrLen1; //call DoneExcept instrLen2 = Disasm.Disassemble(Code + Pos, (__int64)Adr, 0, 0); Adr += instrLen2; if (Adr > lastAdr) lastAdr = Adr; } else if (recN1->SameName("@HandleOnException")) { //jmp HandleOnException Pos += instrLen1; Adr += instrLen1; //dd num num = *((int*)(Code + Pos)); Pos += 4; if (Adr + 4 + 8 * num > lastAdr) lastAdr = Adr + 4 + 8 * num; for (int k = 0; k < num; k++) { //dd offset ExceptionInfo Pos += 4; //dd offset ExceptionProc Pos += 4; } } } } } } curPos += instrLen; curAdr += instrLen; continue; } } while (1) { //Call - stop analyze of arguments if (DisInfo.Call) { lastemb = false; Adr = DisInfo.Immediate; if (IsValidCodeAdr(Adr)) { recN1 = GetInfoRec(Adr); if (recN1 && recN1->procInfo) { lastemb = (recN1->procInfo->flags & PF_EMBED); WORD retb; //@XStrCatN if (recN1->SameName("@LStrCatN") || recN1->SameName("@WStrCatN") || recN1->SameName("@UStrCatN") || recN1->SameName("Format")) { retb = 0; } else retb = recN1->procInfo->retBytes; if (retb && sp >= retb) sp -= retb; else sp = -1; } else sp = -1; //call not always preserve registers eax, edx, ecx if (recN1) { //@IntOver, @BoundErr nothing change if (!recN1->SameName("@IntOver") && !recN1->SameName("@BoundErr")) { argA = argD = argC = false; } } else { argA = argD = argC = false; } } else { argA = argD = argC = false; sp = -1; } break; } //jmp - stop analyze of output arguments if (op == OP_JMP) { lastCallAdr = 0; break; } //cop ..., [ebp + Offset] if (!kb && bpBased && DisInfo.BaseReg == 21 && DisInfo.IndxReg == -1 && (int)DisInfo.Offset > 0) { recN1 = GetInfoRec(fromAdr); //For embedded procs we have on1 additional argument (pushed on stack first), that poped from stack by instrcution pop ecx if (!emb || (int)DisInfo.Offset != retBytes + bpBase) { int argSize = DisInfo.MemSize; String argType = ""; if (argSize == 10) argType = "Extended"; //Each argument in stack has size 4*N bytes if (argSize < 4) argSize = 4; argSize = ((argSize + 3) / 4) * 4; recN1->procInfo->AddArg(0x21, (int)DisInfo.Offset, argSize, "", argType); } } //Instruction pop reg always change reg if (op == OP_POP && DisInfo.OpType[0] == otREG) { //eax if (DisInfo.OpRegIdx[0] == 16) { //Forget last call and set flag cfSkip, if it was call of embedded proc if (lastCallAdr) { if (lastemb) { SetFlag(cfSkip, curPos); lastemb = false; } lastCallAdr = 0; } if (argA && !inA) { argA = false; if (!inD) argD = false; if (!inC) argC = false; } } //edx if (DisInfo.OpRegIdx[0] == 18) { if (argD && !inD) { argD = false; if (!inC) argC = false; } } //ecx if (DisInfo.OpRegIdx[0] == 17) { if (argC && !inC) argC = false; } break; } //cdq always change edx; eax may be output argument of last call if (op == OP_CDQ) { if (lastCallAdr) { recN1 = GetInfoRec(lastCallAdr); if (recN1 && recN1->procInfo && !(recN1->procInfo->flags & (PF_KBPROTO | PF_EVENT | PF_DYNAMIC)) && recN1->kind != ikConstructor && recN1->kind != ikDestructor) { recN1->procInfo->flags |= PF_OUTEAX; recN1->kind = ikFunc; } lastCallAdr = 0; } if (argD && !inD) { argD = false; if (!inC) argC = false; } break; } if (DisInfo.Float) { //fstsw, fnstsw always change eax if (!memcmp(DisInfo.Mnem + 1, "stsw", 4) || !memcmp(DisInfo.Mnem + 1, "nstsw", 5)) { if (DisInfo.OpType[0] == otREG && (DisInfo.OpRegIdx[0] == 16 || DisInfo.OpRegIdx[0] == 8 || DisInfo.OpRegIdx[0] == 4 || DisInfo.OpRegIdx[0] == 0)) { if (lastCallAdr) lastCallAdr = 0; if (argA && !inA) { argA = false; if (!inD) argD = false; if (!inC) argC = false; } } SetFlags(cfSkip, curPos, instrLen); break; } //Instructions fst, fstp after call means that it was call of function if (!memcmp(DisInfo.Mnem + 1, "st", 2)) { Pos = GetNearestUpInstruction(curPos, fromPos, 1); if (Pos != -1 && IsFlagSet(cfCall, Pos)) { if (lastCallAdr) { recN1 = GetInfoRec(lastCallAdr); if (recN1 && recN1->procInfo && !(recN1->procInfo->flags & (PF_KBPROTO | PF_EVENT | PF_DYNAMIC)) && recN1->kind != ikConstructor && recN1->kind != ikDestructor) { recN1->procInfo->flags |= PF_OUTEAX; recN1->kind = ikFunc; } lastCallAdr = 0; } } break; } } //mul, div ????????????????????????????????????????????????????????????????????? //xor reg, reg always change register if (op == OP_XOR && DisInfo.OpType[0] == DisInfo.OpType[1] && DisInfo.OpRegIdx[0] == DisInfo.OpRegIdx[1]) { if (DisInfo.OpRegIdx[0] == 16 || DisInfo.OpRegIdx[0] == 8 || DisInfo.OpRegIdx[0] == 4 || DisInfo.OpRegIdx[0] == 0) { if (lastCallAdr) lastCallAdr = 0; } if (DisInfo.OpRegIdx[0] == 18 || DisInfo.OpRegIdx[0] == 10 || DisInfo.OpRegIdx[0] == 6 || DisInfo.OpRegIdx[0] == 2) { if (lastCallAdr) lastCallAdr = 0; } //eax, ax, ah, al if (DisInfo.OpRegIdx[0] == 16 || DisInfo.OpRegIdx[0] == 8 || DisInfo.OpRegIdx[0] == 4 || DisInfo.OpRegIdx[0] == 0) { SetFlag(cfSetA, curPos); if (argA && !inA) { argA = false; if (!inD) argD = false; if (!inC) argC = false; } } //edx, dx, dh, dl if (DisInfo.OpRegIdx[0] == 18 || DisInfo.OpRegIdx[0] == 10 || DisInfo.OpRegIdx[0] == 6 || DisInfo.OpRegIdx[0] == 2) { SetFlag(cfSetD, curPos); if (argD && !inD) { argD = false; if (!inC) argC = false; } } //ecx, cx, ch, cl if (DisInfo.OpRegIdx[0] == 17 || DisInfo.OpRegIdx[0] == 9 || DisInfo.OpRegIdx[0] == 5 || DisInfo.OpRegIdx[0] == 1) { SetFlag(cfSetC, curPos); if (argC && !inC) argC = false; } break; } //If eax, edx, ecx in memory address - always used as registers if (DisInfo.BaseReg != -1 || DisInfo.IndxReg != -1) { if (DisInfo.BaseReg == 16 || DisInfo.IndxReg == 16) { if (lastCallAdr) { recN1 = GetInfoRec(lastCallAdr); if (recN1 && recN1->procInfo && !(recN1->procInfo->flags & (PF_KBPROTO | PF_EVENT | PF_DYNAMIC)) && recN1->kind != ikConstructor && recN1->kind != ikDestructor) { recN1->procInfo->flags |= PF_OUTEAX; recN1->kind = ikFunc; } lastCallAdr = 0; } } if (DisInfo.BaseReg == 16 || DisInfo.IndxReg == 16) { if (argA && !inA) { inA = true; argA = false; } } if (DisInfo.BaseReg == 18 || DisInfo.IndxReg == 18) { if (argD && !inD) { inD = true; argD = false; if (!inA) { inA = true; argA = false; } } } if (DisInfo.BaseReg == 17 || DisInfo.IndxReg == 17) { if (argC && !inC) { inC = true; argC = false; if (!inA) { inA = true; argA = false; } if (!inD) { inD = true; argD = false; } } } } //xchg if (op == OP_XCHG) { if (DisInfo.OpType[0] == otREG) { if (DisInfo.OpRegIdx[0] == 16) //eax { if (lastCallAdr) { recN1 = GetInfoRec(lastCallAdr); if (recN1 && recN1->procInfo && !(recN1->procInfo->flags & (PF_KBPROTO | PF_EVENT | PF_DYNAMIC)) && recN1->kind != ikConstructor && recN1->kind != ikDestructor) { recN1->procInfo->flags |= PF_OUTEAX; recN1->kind = ikFunc; } lastCallAdr = 0; } } if (DisInfo.OpRegIdx[0] == 16) //eax { SetFlag(cfSetA, curPos); if (argA && !inA) { inA = true; argA = false; } } if (DisInfo.OpRegIdx[0] == 18) //edx { SetFlag(cfSetD, curPos); if (argD && !inD) { inD = true; argD = false; if (!inA) { inA = true; argA = false; } } } if (DisInfo.OpRegIdx[0] == 17) //ecx { SetFlag(cfSetC, curPos); //xchg ecx, [ebp...] - ecx used as argument if (DisInfo.BaseReg == 21) { inC = true; argC = false; if (!inA) { inA = true; argA = false; } if (!inD) { inD = true; argD = false; } //Set cfFrame upto start of procedure SetFlags(cfFrame, fromPos, (curPos + instrLen - fromPos)); } else if (argC && !inC) { inC = true; argC = false; if (!inA) { inA = true; argA = false; } if (!inD) { inD = true; argD = false; } } } } if (DisInfo.OpType[1] == otREG) { if (DisInfo.OpRegIdx[1] == 16) { if (lastCallAdr) { recN1 = GetInfoRec(lastCallAdr); if (recN1 && recN1->procInfo && !(recN1->procInfo->flags & (PF_KBPROTO | PF_EVENT | PF_DYNAMIC)) && recN1->kind != ikConstructor && recN1->kind != ikDestructor) { recN1->procInfo->flags |= PF_OUTEAX; recN1->kind = ikFunc; } lastCallAdr = 0; } } if (DisInfo.OpRegIdx[1] == 16) { SetFlag(cfSetA, curPos); if (argA && !inA) { inA = true; argA = false; } } if (DisInfo.OpRegIdx[1] == 18) { SetFlag(cfSetD, curPos); if (argD && !inD) { inD = true; argD = false; if (!inA) { inA = true; argA = false; } } } if (DisInfo.OpRegIdx[1] == 17) { SetFlag(cfSetC, curPos); if (argC && !inC) { inC = true; argC = false; if (!inA) { inA = true; argA = false; } if (!inD) { inD = true; argD = false; } } } } break; } //cop ..., reg if (DisInfo.OpType[1] == otREG) { if (DisInfo.OpRegIdx[1] == 16 || DisInfo.OpRegIdx[1] == 8 || DisInfo.OpRegIdx[1] == 0) { if (lastCallAdr) { recN1 = GetInfoRec(lastCallAdr); if (recN1 && recN1->procInfo && !(recN1->procInfo->flags & (PF_KBPROTO | PF_EVENT | PF_DYNAMIC)) && recN1->kind != ikConstructor && recN1->kind != ikDestructor) { recN1->procInfo->flags |= PF_OUTEAX; recN1->kind = ikFunc; } lastCallAdr = 0; } } //eax, ax, ah, al if (DisInfo.OpRegIdx[1] == 16 || DisInfo.OpRegIdx[1] == 8 || DisInfo.OpRegIdx[1] == 4 || DisInfo.OpRegIdx[1] == 0) { if (argA && !inA) { inA = true; argA = false; } } //edx, dx, dh, dl if (DisInfo.OpRegIdx[1] == 18 || DisInfo.OpRegIdx[1] == 10 || DisInfo.OpRegIdx[1] == 6 || DisInfo.OpRegIdx[1] == 2) { if (argD && !inD) { inD = true; argD = false; if (!inA) { inA = true; argA = false; } } } //ecx, cx, ch, cl if (DisInfo.OpRegIdx[1] == 17 || DisInfo.OpRegIdx[1] == 9 || DisInfo.OpRegIdx[1] == 5 || DisInfo.OpRegIdx[1] == 1) { if (argC && !inC) { inC = true; argC = false; if (!inA) { inA = true; argA = false; } if (!inD) { inD = true; argD = false; } } } } if (DisInfo.OpType[0] == otREG && op != OP_UNK && op != OP_PUSH) { if (op != OP_MOV && op != OP_LEA && op != OP_SET) { //eax, ax, ah, al if (DisInfo.OpRegIdx[0] == 16 || DisInfo.OpRegIdx[0] == 8 || DisInfo.OpRegIdx[0] == 4 || DisInfo.OpRegIdx[0] == 0) { if (argA && !inA) { inA = true; argA = false; } } //edx, dx, dh, dl if (DisInfo.OpRegIdx[0] == 18 || DisInfo.OpRegIdx[0] == 10 || DisInfo.OpRegIdx[0] == 6 || DisInfo.OpRegIdx[0] == 2) { if (argD && !inD) { inD = true; argD = false; if (!inA) { inA = true; argA = false; } } } //ecx, cx, ch, cl if (DisInfo.OpRegIdx[0] == 17 || DisInfo.OpRegIdx[0] == 9 || DisInfo.OpRegIdx[0] == 5 || DisInfo.OpRegIdx[0] == 1) { if (argC && !inC) { inC = true; argC = false; if (!inA) { inA = true; argA = false; } if (!inD) { inD = true; argD = false; } } } } else { //eax, ax, ah, al if (DisInfo.OpRegIdx[0] == 16 || DisInfo.OpRegIdx[0] == 8 || DisInfo.OpRegIdx[0] == 4 || DisInfo.OpRegIdx[0] == 0) { SetFlag(cfSetA, curPos); if (argA && !inA) { argA = false; if (!inD) argD = false; if (!inC) argC = false; } if (lastCallAdr) lastCallAdr = 0; } //edx, dx, dh, dl if (DisInfo.OpRegIdx[0] == 18 || DisInfo.OpRegIdx[0] == 10 || DisInfo.OpRegIdx[0] == 6 || DisInfo.OpRegIdx[0] == 2) { SetFlag(cfSetD, curPos); if (argD && !inD) { argD = false; if (!inC) argC = false; } if (lastCallAdr) lastCallAdr = 0; } //ecx, cx, ch, cl if (DisInfo.OpRegIdx[0] == 17 || DisInfo.OpRegIdx[0] == 9 || DisInfo.OpRegIdx[0] == 5 || DisInfo.OpRegIdx[0] == 1) { SetFlag(cfSetC, curPos); if (argC && !inC) argC = false; } } } break; } if (DisInfo.Call) //call sub_XXXXXXXX { lastCallAdr = 0; Adr = DisInfo.Immediate; if (IsValidCodeAdr(Adr)) { retType = AnalyzeArguments(Adr); lastCallAdr = Adr; recN1 = GetInfoRec(Adr); if (recN1 && recN1->HasName()) { //Hide some procedures //@Halt0 is not executed if (recN1->SameName("@Halt0")) { SetFlags(cfSkip, curPos, instrLen); if (fromAdr == EP && !lastAdr) break; } //Procs together previous unstruction else if (recN1->SameName("@IntOver") || recN1->SameName("@InitImports") || recN1->SameName("@InitResStringImports")) { Pos = GetNearestUpInstruction(curPos, fromPos, 1); if (Pos != -1) SetFlags(cfSkip, Pos, (curPos - Pos) + instrLen); } //@BoundErr else if (recN1->SameName("@BoundErr")) { if (IsFlagSet(cfLoc, curPos)) { Pos = GetNearestUpInstruction(curPos, fromPos, 1); Disasm.Disassemble(Code + Pos, (__int64)Pos2Adr(Pos), &DisInfo1, 0); if (DisInfo1.Branch) { Pos = GetNearestUpInstruction(Pos, fromPos, 3); SetFlags(cfSkip, Pos, (curPos - Pos) + instrLen); } } else { Pos = GetNearestUpInstruction(curPos, fromPos, 1); Disasm.Disassemble(Code + Pos, (__int64)Pos2Adr(Pos), &DisInfo1, 0); if (DisInfo1.Branch) { Pos = GetNearestUpInstruction(Pos, fromPos, 1); if (IsFlagSet(cfPop, Pos)) { Pos = GetNearestUpInstruction(Pos, fromPos, 3); } SetFlags(cfSkip, Pos, (curPos - Pos) + instrLen); } } } //Not in source code else if (recN1->SameName("@_IOTest") || recN1->SameName("@InitExe") || recN1->SameName("@InitLib") || recN1->SameName("@DoneExcept")) { SetFlags(cfSkip, curPos, instrLen); } } } curPos += instrLen; curAdr += instrLen; continue; } if (b1 == 0xEB || //short relative abs jmp or cond jmp (b1 >= 0x70 && b1 <= 0x7F) || (b1 == 0xF && b2 >= 0x80 && b2 <= 0x8F)) { Adr = DisInfo.Immediate; if (IsValidCodeAdr(Adr)) { if (Adr >= fromAdr && Adr > lastAdr) lastAdr = Adr; } curPos += instrLen; curAdr += instrLen; continue; } if (b1 == 0xE9) //relative abs jmp or cond jmp { Adr = DisInfo.Immediate; if (IsValidCodeAdr(Adr)) { recN1 = GetInfoRec(Adr); if (!recN1 && Adr >= fromAdr && Adr > lastAdr) lastAdr = Adr; } curPos += instrLen; curAdr += instrLen; continue; } curPos += instrLen; curAdr += instrLen; } //Check matching ret bytes and summary size of stack arguments if (bpBased) { if (recN->procInfo->args) { int delta = retBytes; for (int n = 0; n < recN->procInfo->args->Count; n++) { argInfo = (PARGINFO)recN->procInfo->args->Items[n]; if (argInfo->Ndx > 2) delta -= argInfo->Size; } if (delta < 0) { //If delta between N bytes (in "ret N" instruction) and total size of argumnets != 0 recN->procInfo->flags |= PF_ARGSIZEG; //delta = 4 and proc can be embbedded - allow that it really embedded if (delta == 4 && (recN->procInfo->flags & PF_MAYBEEMBED)) { //Ставим флажок PF_EMBED recN->procInfo->flags |= PF_EMBED; //Skip following after call instrcution "pop ecx" for (int n = 0; n < recN->xrefs->Count; n++) { PXrefRec recX = (PXrefRec)recN->xrefs->Items[n]; if (recX->type == 'C') { Adr = recX->adr + recX->offset; Pos = Adr2Pos(Adr); instrLen = Disasm.Disassemble(Code + Pos, (__int64)Adr, &DisInfo, 0); Pos += instrLen; if (Code[Pos] == 0x59) SetFlag(cfSkip, Pos); } } } } //If delta < 0, then part of arguments can be unusable else if (delta < 0) { recN->procInfo->flags |= PF_ARGSIZEL; } } } recN = GetInfoRec(fromAdr); //if PF_OUTEAX not set - Procedure if (!kb && !(recN->procInfo->flags & PF_OUTEAX)) { if (recN->kind != ikConstructor && recN->kind != ikDestructor) { recN->kind = ikProc; } } recN->procInfo->stackSize = procStackSize + 0x1000; if (lastCallAdr) return retType; return ""; }
//--------------------------------------------------------------------------- void __fastcall TFMain_11011981::ShowUnitItems(PUnitRec recU, int topIdx, int itemIdx) { bool unk = false; bool imp, exp, emb, xref; int wid, maxwid = 0; TCanvas *canvas = lbUnitItems->Canvas; String line, prefix; if (!CurUnitAdr) return; //if (AnalyzeThread) AnalyzeThread->Suspend(); lbUnitItems->Clear(); lbUnitItems->Items->BeginUpdate(); for (DWORD adr = recU->fromAdr; adr < recU->toAdr; adr++) { int unknum, pos = Adr2Pos(adr); if (!IsFlagSet(~cfLoc, pos)) { BYTE b0 = *(Code + pos); if (!unk) { unknum = 0; BYTE b1 = *(Code + pos + 1); BYTE b2 = *(Code + pos + 2); if ((adr & 3) == 3 && (b0 == 0 || b0 == 0x90)) continue; if ((adr & 3) == 2 && ((b0 == 0 && b1 == 0) || (b0 == 0x8B && b1 == 0xC0) || (b0 == 0x90 && b1 == 0x90))) { adr++; continue; } if ((adr & 3) == 1 && ((b0 == 0 && b1 == 0 && b2 == 0) || (b0 == 0x8D && b1 == 0x40 && b2 == 0) || (b0 == 0x90 && b1 == 0x90 && b2 == 0x90))) { adr += 2; continue; } line = " " + Val2Str8(adr) + " ????"; line[1] ^= 1; line += " " + Val2Str2(b0); unknum++; unk = true; } else { if (unknum <= 16) { if (unknum == 16) line += "..."; else line += " " + Val2Str2(b0); unknum++; } } continue; } if (unk) { lbUnitItems->Items->Add(line); wid = canvas->TextWidth(line); if (wid > maxwid) maxwid = wid; unk = false; } if (adr == recU->iniadr) continue; if (adr == recU->finadr) continue; //EP if (adr == EP) { line = " " + Val2Str8(adr) + " <Proc> EntryPoint"; lbUnitItems->Items->Add(line); wid = canvas->TextWidth(line); if (wid > maxwid) maxwid = wid; continue; } PInfoRec recN = GetInfoRec(adr); if (!recN) continue; BYTE kind = recN->kind; //Skip calls, that are in the body of some asm-procs (for example, FloatToText from SysUtils) if (kind >= ikRefine && kind <= ikFunc && recN->procInfo && (recN->procInfo->flags & cfEmbedded)) continue; imp = IsFlagSet(cfImport, pos); exp = IsFlagSet(cfExport, pos); emb = false; if (IsFlagSet(cfProcStart, pos)) { if (recN->procInfo) { emb = (recN->procInfo->flags & PF_EMBED); } } xref = false; line = ""; switch (kind) { case ikInteger: case ikChar: case ikEnumeration: case ikFloat: case ikSet: case ikClass: case ikMethod: case ikWChar: case ikLString: case ikVariant: case ikArray: case ikRecord: case ikInterface: case ikInt64: case ikDynArray: case ikUString: case ikClassRef: case ikPointer: case ikProcedure: line = "<" + TypeKind2Name(kind) + "> "; if (recN->HasName()) { if (recN->GetNameLength() <= MAXLEN) line += recN->GetName(); else { line += recN->GetName().SubString(1, MAXLEN) + "..."; } } break; case ikString: if (!IsFlagSet(cfRTTI, pos)) line = "<ShortString> "; else line = "<" + TypeKind2Name(kind) + "> "; if (recN->HasName()) { if (recN->GetNameLength() <= MAXLEN) line += recN->GetName(); else { line += recN->GetName().SubString(1, MAXLEN) + "..."; } } break; case ikWString: line = "<WideString> "; if (recN->HasName()) { if (recN->GetNameLength() <= MAXLEN) line += recN->GetName(); else { line += recN->GetName().SubString(1, MAXLEN) + "..."; } } break; case ikCString: line = "<PAnsiChar> "; if (recN->HasName()) { if (recN->GetNameLength() <= MAXLEN) line += recN->GetName(); else { line += recN->GetName().SubString(1, MAXLEN) + "..."; } } break; case ikWCString: line = "<PWideChar> "; if (recN->HasName()) { if (recN->GetNameLength() <= MAXLEN) line += recN->GetName(); else { line += recN->GetName().SubString(1, MAXLEN) + "..."; } } break; case ikResString: if (recN->HasName()) line += "<ResString> " + recN->GetName() + "=" + recN->rsInfo->value; break; case ikVMT: line = "<VMT> "; if (recN->HasName()) line += recN->GetName(); break; case ikConstructor: xref = true; line = "<Constructor> " + recN->MakePrototype(adr, false, true, false, true, false); break; case ikDestructor: xref = true; line = "<Destructor> " + recN->MakePrototype(adr, false, true, false, true, false); break; case ikProc: xref = true; line = "<"; if (imp) line += "Imp"; else if (exp) line += "Exp"; else if (emb) line += "Emb"; line += "Proc> " + recN->MakePrototype(adr, false, true, false, true, false); break; case ikFunc: xref = true; line = "<"; if (imp) line += "Imp"; else if (exp) line += "Exp"; else if (emb) line += "Emb"; line += "Func> " + recN->MakePrototype(adr, false, true, false, true, false); break; case ikGUID: line = "<TGUID> "; if (recN->HasName()) line += recN->GetName(); break; case ikRefine: xref = true; line = "<"; if (imp) line += "Imp"; else if (exp) line += "Exp"; else if (emb) line += "Emb"; line += "?> " + recN->MakePrototype(adr, false, true, false, true, false); break; default: if (IsFlagSet(cfProcStart, pos)) { xref = true; if (recN->kind == ikConstructor) line = "<Constructor> " + recN->MakePrototype(adr, false, true, false, true, false); else if (recN->kind == ikDestructor) line = "<Destructor> " + recN->MakePrototype(adr, false, true, false, true, false); else { line = "<"; if (emb) line += "Emb"; line += "Proc> " + recN->MakePrototype(adr, false, true, false, true, false); } } break; } if (kind >= ikRefine && kind <= ikFunc) { if (recN->procInfo->flags & PF_VIRTUAL) line += " virtual"; if (recN->procInfo->flags & PF_DYNAMIC) line += " dynamic"; if (recN->procInfo->flags & PF_EVENT) line += " event"; } if (line != "") { prefix = " " + Val2Str8(adr); if (xref && recN->xrefs && recN->xrefs->Count) { prefix[1] ^= 2; for (int m = 0; m < recN->xrefs->Count; m++) { PXrefRec recX = (PXrefRec)recN->xrefs->Items[m]; PUnitRec recU = GetUnit(recX->adr); if (recU && !recU->kb) { prefix[1] ^= 4; break; } } prefix += " " + String(recN->xrefs->Count); if (recN->xrefs->Count <= 9) prefix += " "; else if (recN->xrefs->Count <= 99) prefix += " "; } line = prefix + " " + line; lbUnitItems->Items->Add(line); wid = canvas->TextWidth(line); if (wid > maxwid) maxwid = wid; } } //Add initialization procedure if (recU->iniadr) { line = " " + Val2Str8(recU->iniadr) + " <Proc> Initialization;"; lbUnitItems->Items->Add(line); wid = canvas->TextWidth(line); if (wid > maxwid) maxwid = wid; } //Add finalization procedure if (recU->finadr) { line = " " + Val2Str8(recU->finadr) + " <Proc> Finalization;"; lbUnitItems->Items->Add(line); wid = canvas->TextWidth(line); if (wid > maxwid) maxwid = wid; } lbUnitItems->TopIndex = topIdx; lbUnitItems->ItemIndex = itemIdx; lbUnitItems->ScrollWidth = maxwid + 2; lbUnitItems->ItemHeight = lbUnitItems->Canvas->TextHeight("T"); lbUnitItems->Items->EndUpdate(); //if (AnalyzeThread) AnalyzeThread->Resume(); }