⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcwiz0.cpp

📁 Decompilation Dos Program is a technique that allows you to recover lost source code. It is also nee
💻 CPP
📖 第 1 页 / 共 2 页
字号:
[ ProcBegin - Beginning of the procedure.				]
[ Recurse - 1 if we can recursively search all procedures for functions	]
[	called and variables used and setup all the related lists.	]
[-----------------------------------------------------------------------]
*/
void TcWizard::Pass1(Byte far *ProcBegin,int Recurse)
{
  Flush();
  static int SwitchFormat[]={ CMP,JA,SHL,SEGMENT,JMP };
  Byte far *Inst;
  Disasm d;
  d.SetCodePtr(CodePtr);
  Dword ProcSize;
  Dword ctr = SkipProcInit(ProcBegin,ProcSize);
  // This initialization of ProcEndAddress is a must, in pass1.
  // this prevents from tracing instructions after the end of the
  // given procedure.
  ProcEndAddress = ProcBegin + ctr + ProcSize;
  Inst = ProcBegin + ctr;
  Byte far *tInstBegin = Inst;
  int NumBlocksFound=0;
  if (BlockTable) free(BlockTable);
  Byte far **ProcTable=NULL;
  char *ProcNames;
  int *ProcPercent;
  int NumProcsCalled;
ComForFindAndStore:
  ctr=0;
  NumBlocks = 0;
  NumProcsCalled=0;
  while(ctr<ProcSize)
  {
    int val,i,oper;
    int InstLen;
    d.TraceInst(Inst,InstLen);
    Inst += InstLen;
    ctr += InstLen;
    InstInfo inst = d.CurInst;
    TranslateTrickyInsts(inst);
    switch(inst.Instr)
    {
      // forming a list of functions called by this procedure.
      case CALL: if (NumBlocksFound)
		 {
		   Word seg=FP_SEG(ProcBegin);
		   if (inst.operSize1) seg=inst.Data12;
		   Byte far *p=(Byte far *)MK_FP(seg,inst.Data11);
		   Variable v;
		   v.Operand=IMMEDIATE;
		   v.Data1=FP_OFF(p);
		   v.Data2=FP_SEG(p);
		   // if the procedure has already been scanned, skip it.
		   if (GlobalVars.IsPresent(v)) break;
		   // Check if an entry has already been made
		   for(int i=0;i<NumProcsCalled;i++)
		     if (ProcTable[i]==p) break;
		   // no?
		   if (i==NumProcsCalled)
		   {
		     ProcTable[NumProcsCalled++]=p;
		   }
		 }
		 else NumProcsCalled++;
		 break;
      // checking for the Ordered-Switch.
      case CMP : Byte far *tInst = Inst; int tInstLen;
		 for(int i=1;i<5;i++)
		 {
		   d.TraceInst(tInst,tInstLen);
		   if (d.CurInst.Instr!=SwitchFormat[i]) break;
		   tInst+=tInstLen;
		 }
		 if (i==5)
		 {
		   if (NumBlocksFound)
		   {
		     BlockTable[NumBlocks].Type = C_SWITCH_ORDERED;
		     BlockTable[NumBlocks].Address = FP_OFF(Inst-InstLen);
		   }
		   NumBlocks++;
		 }
		 break;
      case RET : ctr = ProcSize; break;
      // Loop means that we got the address of a SWITCH statement.
      case LOOP:if (NumBlocksFound)
		{
		  BlockTable[NumBlocks].Type = C_SWITCH;
		  BlockTable[NumBlocks].Address = inst.Data11;
		}
		NumBlocks++;
		break;
//	JA, JAE, JB, JBE, JZ, JNZ, JG, JGE, JL, JLE
//	Others normally do not occur in C Programs. Hence ignored.
      case JMP :
		if (inst.Operand1!=IMMEDIATE) break;
      case JA : case JAE : case JB : case JBE :
      case JL : case JG  : case JZ :
      case JLE: case JGE : case JNZ:
		if (NumBlocksFound)
		{
		  // Check if the address is already present in the table.
		  for(register int i=0;i<NumBlocks;i++)
		    if (BlockTable[i].Type==C_GOTO && \
			BlockTable[i].Address==inst.Data11) break;
		  // If not, store it.
		  if (i<=NumBlocks)
		  {
		    BlockTable[NumBlocks].Type = C_GOTO;
		    BlockTable[NumBlocks].Address = inst.Data11;
		    NumBlocks++;
		  }
		}
		else NumBlocks++;
		break;
    }
  }
  if (!NumBlocksFound)
  {
    if (NumBlocks)
    {
      BlockTable = (CBlock *)malloc(sizeof(CBlock)*NumBlocks);
      if (!BlockTable)
      {
	ErrorList.Add("Not enough memory in Pass1!");
	exit(1);
      }
      NumBlocksFound=1;
    }
    if (NumProcsCalled)
    {
      ProcTable = (Byte far **)malloc(
	sizeof(Byte far *)*NumProcsCalled +
	sizeof(int)*NumProcsCalled +
	sizeof(char)*64*NumProcsCalled);
      if (!ProcTable)
      {
	ErrorList.Add("Not enough memory in Pass1!");
	exit(1);
      }
      ProcPercent=(int *)(ProcTable+NumProcsCalled);
      ProcNames=(char *)(ProcPercent+NumProcsCalled);
      NumBlocksFound=1;
    }
    if (NumBlocksFound)
    {
      Inst=tInstBegin;
      goto ComForFindAndStore;
    }
  }
  qsort(BlockTable,NumBlocks,sizeof(CBlock),sortFunc);
  // Now find the library functions.
  TLibWizard tlw;
  if (tlw.CheckInLibrary("cs.lib",NumProcsCalled,ProcTable,ProcNames,ProcPercent)==0)
  {
    Variable v;
    for(int i=0;i<NumProcsCalled;i++)
    {
      v.Operand=IMMEDIATE;
      v.Data1=FP_OFF(ProcTable[i]);
      v.Data2=FP_SEG(ProcTable[i]);
      if (ProcPercent[i]>950)
	GlobalVars.Add(v,VAR_LIB_FUNCTION,0,ProcNames+i*64);
      else
      {
	GlobalVars.Add(v,VAR_USER_FUNCTION,0,NULL);
	sprintf(errorStr,"Function at address %Fp not found in library",ProcTable[i]);
	ErrorList.Add(errorStr);
	if (Recurse) Pass1(ProcTable[i],Recurse);
      }
    }
  }
  if (ProcTable) free(ProcTable);
  // Go thro' the procedure once and register all variables whose datatypes
  //  can be found from the code structure.
  // ** Do it only if we aren't going recursively.  If so, the caller will
  // **  do this checking.
  TranslateBlock(tInstBegin,ProcSize,SEPARATE_LINES,NULL);
}
void TcWizard::Output(const char *Statement, int How, StringList *sList)
{
  String tmp,tmp1,tmp2;
  if (TracingFunctionCall) How=COMMA_EXPRESSIONS;
  Word iAddr;
  while(FlushPending(tmp2,iAddr))
  {
    switch(How)
    {
      case SEPARATE_LINES    :
		tmp = tmp2+";";
		if (sList) sList->Add(tmp,iAddr);
		break;
      case COMMA_EXPRESSIONS : tmp1 += tmp2; tmp1 += ","; break;
    }
  }
  if (Statement)		// Pass NULL to do only Flushing of pending
  {				//  lines.
    switch(How)
    {
      case SEPARATE_LINES    :
		tmp = "";
		tmp += Statement;
		if (sList) sList->Add(tmp,InstAddr); break;
      case COMMA_EXPRESSIONS : tmp1 += Statement;
		char *ptr = (char *)tmp1;
		int len = strlen(ptr);
		if (ptr[len]==';') ptr[len]=',';
		else tmp1 += ",";
		break;
    }
  }
  if (How==COMMA_EXPRESSIONS)
  {
    if (TracingFunctionCall)
    {
      int i=StackTop;
      if (((char *)Stack[i])[0] == 0) Stack[i] = "(";
      Stack[i] += tmp1;
    }
    else
    {
      if (sList) sList->Add(tmp1);
    }
  }
}
void TcWizard::DisplayProc(Byte far *ProcBegin)
{
  StringList sList;
  Dword ProcSize;
  Dword ctr = SkipProcInit(ProcBegin,ProcSize);
  InstAddr=FP_OFF(ProcBegin+ctr);
  Variable v;
  v.Operand=IMMEDIATE;
  v.Data1=FP_OFF(ProcBegin);
  v.Data2=FP_SEG(ProcBegin);
  char FuncName[35];
  if (FuncName) strcpy(FuncName,GlobalVars.GetName(v));
  else strcpy(FuncName,(char *)String((Word)v.Data1));
  strcat(FuncName,"()");
  Output(FuncName,SEPARATE_LINES,&sList);
  Output("{",SEPARATE_LINES,&sList);

  // this initialization is a must in displayproc and pass1
  ProcEndAddress=ProcBegin+ctr+ProcSize;

  TranslateBlock(ProcBegin+ctr,ProcSize,SEPARATE_LINES,&sList);
  Output("}",SEPARATE_LINES,&sList);
  CBeautifier cb;
  printf("\nRestructure code(Y/N)?\n");
  int i=getch();
  if (i=='y' || i=='Y') cb.BeautifyCode(&sList);
  FILE *fp=fopen("_disc.c","a");
  if (!fp) fp=fopen("_disc.c","w");
  if (!fp) printf("Unable to open _disc.c\n");
  else
  {
    cb.DisplayList(&sList,fp);
    printf("Written to file.\n");
    fclose(fp);
  }
}
/*
[-----------------------------------------------------------------------]
[ CheckForTernaryOperCode - must be called only by TranslateBlock.	]
[-----------------------------------------------------------------------]
[ Logic: Ternary operator compiles as					]
[	 CMP val1,val2							]
[   [--- Jxx label1							]
[   |	 ...								]
[   |[-- JMP label2							]
[   [--	label1:								]
[    |	 ...								]
[    [- label2:								]
[	 possible assignment code etc.					]
[	 ##End of ternary operator code.				]
[   Find the 1st JMP from CMP, find the address given in the JMP(this is]
[	the end of the block).						]
[   Find if any registers are modified and not used in the block	]
[	(possibly used after the block(i.e. are you using the result of	]
[	the ternary operator). If so, then 'tis a ternary operator.	]
[ Code - points to the instruction after the Jxx to be checked.		]
[ ConditionStr - points to the condition eg. (i==1)			]
[-----------------------------------------------------------------------]
*/
Byte far *TcWizard::CheckForTernaryOperCode(Byte far *Code,char *ConditionStr)
{
  Disasm d;
  d.SetCodePtr(CodePtr);
  Byte far *Inst = Code;
  int InstLen;
  // Find the JMP and the end of the block from that instruction.
  // If we have another ternary operator inside this block, we must skip
  //  the JMP of the second block, so that we find the JMP of this first
  //  ternary operator correctly.
  int NumJumpsToSkip=0;
  Byte far *Fragment1Begin=0; Word Fragment1Size=0;
  Byte far *Fragment2Begin=0; Word Fragment2Size=0;
  Word ctr=0,BlockSize=CompareVar.EndAddress-FP_OFF(Code);
  while(ctr<BlockSize)
  {
    d.TraceInst(Inst,InstLen);
    if (d.CurInst.Instr==JMP)
    {
      if (!NumJumpsToSkip)
      {
	// Now Inst points to the JMP instruction.
	Fragment1Begin = Code;
	Fragment2Begin = Inst+InstLen;
	Byte far *Fragment2End = (Byte far *)MK_FP(d.CurInst.Data21,d.CurInst.Data11);
	Fragment1Size = Inst - Fragment1Begin;
	Fragment2Size = Fragment2End - Fragment2Begin;
	break;
      }
      else NumJumpsToSkip--;
    }
    else if (d.CurInst.Instr==CMP) NumJumpsToSkip++;
    Inst += InstLen;
    ctr += InstLen;
  }
  // Error in searching for the JMP?
  if (ctr==BlockSize) return Code;
  if (Fragment1Size<=0 || Fragment2Size<=0) return Code;
  int i;
  // Now find which registers are modified in the first code fragment.
  Byte RegModified[8+8];	// No SegmentRegisters are checked here.
  Byte RegUsed[8+8];
  Byte RegModifiedLater[8+8];
  Byte RegUsedLater[8+8];
  for(i=0;i<16;i++)
  {
    RegModified[i]=0; RegUsed[i]=0;
    RegModifiedLater[i]=0; RegUsedLater[i]=0;
  }

  TcWizardState CurState;
  SaveState(CurState);

  FindRegsUsed(Fragment1Begin,Fragment1Size,RegModified,RegUsed);
  RestoreState(CurState);
  FindRegsUsed(Fragment2Begin+Fragment2Size,15,RegModifiedLater,RegUsedLater);
  RestoreState(CurState);
  // Check if any of the registers were modified, but not used later.
  // *** Check if RegModified[i]==1, since RegModified[i]==2 if there
  // ***  was a function call, whose return value type is not known.
  // *** Ignore such Modifications to the register values here.
  for(i=0;i<16;i++)
    if ((RegModified[i]==1 && !RegUsed[i]) &&
	(RegModifiedLater[i]!=1 && RegUsedLater[i]))
    break;
  // No such registers? Well, then this is not a ternary operator code.
  if (i==16) return Code;

  String t; t=ConditionStr;
  String tRegs[16];
  // Giving SEPARATE_LINES or COMMA_EXPRESSIONS here doesn't matter, because
  //  sList = NULL here.
  TranslateBlock(Fragment2Begin,Fragment2Size,SEPARATE_LINES,NULL);
  for(i=0;i<16;i++) tRegs[i] = t + " ? (" + Regs[i] + ") : (";
  RestoreState(CurState);
  TranslateBlock(Fragment1Begin,Fragment1Size,SEPARATE_LINES,NULL);
  // Now change only those registers used in the ternary operator code.
  for(i=0;i<16;i++)
    if ((RegModified[i]==1 && !RegUsed[i]) &&
	(RegModifiedLater[i]!=1 && RegUsedLater[i]))
      tRegs[i] += Regs[i] + ")";
  RestoreState(CurState);
  for(i=0;i<16;i++)
    if ((RegModified[i]==1 && !RegUsed[i]) &&
	(RegModifiedLater[i]!=1 && RegUsedLater[i]))
    {
      // support for long-int returning ternary operators.
      if (i==REG_DX || i==REG_CX) Regs[i]="HIWORD("; else Regs[i]="";
      Regs[i] += tRegs[i];
      if (i==REG_DX || i==REG_CX) Regs[i]+=")";
    }

  DestroyState(CurState);
  return Fragment2Begin+Fragment2Size;
}
int TcWizard::IsEqualClosingParentheses(String &t)
{
  char *ptr = (char *)t;
  int OpeningParentheses=0,ClosingParentheses=0;
  while(*ptr)
  {
    if (*ptr=='(') OpeningParentheses++;
    else if (*ptr==')') ClosingParentheses++;
    ptr++;
  }
  return (OpeningParentheses==ClosingParentheses);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -