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

📄 dcprocinstr.pas

📁 这是个反向工程delphi的程序的全部源代码.能分析几乎所有的结构 Revendepro is a program to reverse engineer Delphi program. Reven
💻 PAS
📖 第 1 页 / 共 2 页
字号:
         Succeeded(TAssignInstr(Items[I -1]).Target.QueryInterface(IRegSource, ARegTarget)) and
         (ARegTarget.RegType = rtDWord) and
         // The Target is set again and not used before it is set again
         ReplCallback.IsRegSetAgain(ARegTarget.Reg, I, False) then
      begin
        // Replace Target of the first instr with the source, except by the True target of the second instr.
        ASource := TAssignInstr(Items[I]).Source.Replace(
            TAssignInstr(Items[I -1]).Target, TAssignInstr(Items[I -1]).Source);
        if not Succeeded(TAssignInstr(Items[I]).Target.QueryInterface(IRegSource, ARegTarget)) then
          ATarget := TAssignInstr(Items[I]).Target.Replace(
              TAssignInstr(Items[I -1]).Target, TAssignInstr(Items[I -1]).Source)
        else
          ATarget := TAssignInstr(Items[I]).Target;
        Instr := TAssignInstr.CreateAssign(Items[I -1].Address, Items[I].Size + Items[I -1].Size, ATarget, ASource);
        TInstruction(FItems[I -1]).Free;
        TInstruction(FItems[I]).Free;
        FItems[I -1] := Instr;
        FItems.Delete(I);
        FChanged := True;
      end;
    end;
  finally
    ReplCallback.Free;
  end;
end;

procedure TdcInstructions.OptimizeSources;
// Optimize all the sources.
var
  ANewSource: IInstrSource;
  ANewTarget: IInstrSource;
  I: Integer;
  Instr: TInstruction;
begin
  for I := 0 to Count -1 do
    if (Items[I] is TAssignInstr) then
    begin
      ANewSource := TAssignInstr(Items[I]).Source.Optimize;
      ANewTarget := TAssignInstr(Items[I]).Target.Optimize;
      if not (ANewSource.Compare(TAssignInstr(Items[I]).Source) and
              ANewTarget.Compare(TAssignInstr(Items[I]).Target)) then
      begin
        FChanged := True;
        Instr := TAssignInstr.CreateAssign(Items[I].Address, Items[I].Size, ANewTarget, ANewSource);
        Items[I].Free;
        FItems[I] := Instr;
      end;
    end;
end;

function TdcInstructions.GetAddress: TAddress;
begin
  Result := FProc.Address;
end;

function TdcInstructions.GetSize: Integer;
begin
  Result := TProc(FProc).ProcSize;
end;

function TdcInstructions.GetCount: Integer;
begin
  Result := FItems.Count;
end;

function TdcInstructions.GetItem(Index: Integer): TInstruction;
begin
  Result := TInstruction(FItems[Index]);
end;

function TdcInstructions.GetItemIndex(Item: TInstruction): Integer;
resourcestring
  EItemNotFound = 'Item not found in instruction list.';
begin
  Result := FItems.IndexOf(Item);
  if Result = -1 then
    raise EDecompilerError.Create(EItemNotFound);
end;

function TdcInstructions.GetText: TStrings;
begin
  Result := FText;
  if Result = nil then
  begin
    FText := TStringList.Create;
    Result := FText;
    // Get the instructions in pascal, or if failed in Assembler.
    if not InstrToPascal(Result) then
      GetAsmInstr(TProc(Proc), Result);
  end;
end;

type
  TUsedSourceCallback = class(TObject)
  private
    Used: set of TRegister;
    procedure TargetCallback(Source: IInstrSource);
    procedure SourceCallback(Source: IInstrSource);
  end;

procedure TUsedSourceCallback.TargetCallback(Source: IInstrSource);
var
  RegSource: IRegSource;
begin
  // Is is a a reg source and the register is not already used, mark it as used.`
  if Succeeded(Source.QueryInterface(IRegSource, RegSource)) then
    Used := Used + [RegSource.Reg];
end;

procedure TUsedSourceCallback.SourceCallback(Source: IInstrSource);
var
  RegSource: IRegSource;
begin
  // Is is a a reg source and the register is not already used, mark it
  // as used before write and used.
  if Succeeded(Source.QueryInterface(IRegSource, RegSource)) then
    Used := Used + [RegSource.Reg];
end;

type
  TRegNames = array[TRegister] of string;
  TPascalCallback = class(TObject)
  private
    PascalRegNames: TRegNames;
    PascalProc: TProc;
    procedure Callback(Source: IInstrSource; var AsPascal: string);
  end;

procedure TPascalCallback.Callback(Source: IInstrSource; var AsPascal: string);
var
  RegSource: IRegSource;
  AddressSource: IAddressSource;
resourcestring
  ERegWithoutAName = 'Reg doesn''t have a name (Bug in code)';
  EFixupConstError = 'A Const value which is a fixup. Not yet supported.';
begin
  // If it is a RegSource replace the AsPascal with the RegName
  if Succeeded(Source.QueryInterface(IRegSource, RegSource)) then
  begin
    AsPascal := PascalRegNames[RegSource.Reg];
    if AsPascal = '' then
      raise EDecompilerError.Create(ERegWithoutAName);
  end;
  if Succeeded(Source.QueryInterface(IAddressSource, AddressSource)) then
    raise EdcInstructionError.Create(EFixupConstError);
end;

function TdcInstructions.InstrToPascal(Strings: TStrings): Boolean;
const
  ProcDef: array[TProcType, Boolean] of string =
    (('procedure  %s(%s);', 'function %s(%s): %s;'), ('class procedure %s.%s(%s);', 'class function %s.%s(%s): %s;'),
     ('procedure %s.%s(%s);', 'function %s.%s(%s): %s;'), ('constructor %s.%s(%s);', 'constructor %s.%s(%s);'),
     ('destructor %s.%s(%s);', 'destructor %s.%s(%s);'), ('', ''), ('', ''), ('', ''));
var
  I: Integer;
  UsedSourceCallback: TUsedSourceCallback;
  Vars: set of TRegister;
  Params: set of TRegister;
  RegNames: TRegNames;
  Reg: TRegister;
  RegSource: IRegSource;
  StackParams: Integer;
  ParamsStr: string;
resourcestring
  ENot4MultiplyRet = 'Stack is not popup by a multiply of 4.';
begin
  Result := False;
  try
    // Must be a Strings object passed.
    if Strings = nil then
      Exit;

    // The proc must be only assign instructions.
    for I := 0 to Count -2 do
      if not (Items[I] is TAssignInstr) then
        Exit;
    // Except the last one which must be a ret instruction.
    if not ((Count > 0) and (Items[count -1] is TRetInstr)) then
      Exit;

    // The proc may not already have parameters or a function result,
    // The proc may also not be a initialization or finalization method.
    // The proc must also be a static proc.
    with TProc(Proc) do
      if (Parameters.Parameters <> '') or (Parameters.FuncResult <> '') or
         (ProcType in [ptInitialization, ptFinalization]) or
         (MethodBindingType <> mbtStatic) then
        Exit;

    // Generate a list of register which is read before they are set.
    UsedSourceCallback := TUsedSourceCallback.Create;
    try
      Params := [];
      for I := 0 to Count -2 do
      begin
        TAssignInstr(Items[I]).Source.GetSources(UsedSourceCallback.SourceCallback);
        if Succeeded(TAssignInstr(Items[I]).Target.QueryInterface(IRegSource, RegSource)) and
           (not (RegSource.Reg in UsedSourceCallback.Used)) then
          Params := Params + [RegSource.Reg];
        TAssignInstr(Items[I]).Target.GetSources(UsedSourceCallback.TargetCallback);
      end;
      Vars := UsedSourceCallback.Used;
    finally
      UsedSourceCallback.Free;
    end;

    // If this list contains other registers then eax, edx and ecx, we don't do this,
    // because there is now way to get access to these registers except assembler.
    if (Params >= [rEax, rEdx, rEcx]) or (Vars >= [rEax, rEdx, rEcx]) then
      Exit;

    // Include also the register for the previous Parameter.
    if rEcx in Params then
      Params := Params + [rEax, rEcx]
    else if rEdx in Params then
      Params := Params + [rEax];

    // If eax is totally not used, it might simply be re return value.
    if not ((rEax in Params) and (rEax in Vars)) then
      Params := Params + [rEax];

    // Ret AA , AA must be a multiply of 4.
    if TRetInstr(Items[Count -1]).PopSize mod 4 <> 0 then
      raise EdcInstructionError.Create(ENot4MultiplyRet);

    // Stack Params is AA / 4 (Ret AA).
    StackParams := TRetInstr(Items[Count -1]).PopSize div 4;

    if StackParams > 0 then
    begin
      // If there are stack parameters and others, all other must be used.
      if Params <> [] then
        Params := Params + [rEax, rEdx, rEcx];
    end;

    Vars := Vars - Params;

    // Generate names for the registers.
    for Reg := Low(TRegister) to High(TRegister) do
    begin
      if Reg in Params then
        RegNames[Reg] := 'Param' + GetEnumName(TypeInfo(TRegister), Integer(Reg));
      if Reg in Vars then
        RegNames[Reg] := 'Var' + GetEnumName(TypeInfo(TRegister), Integer(Reg));
    end;

    // There must be return value.
    TProc(Proc).Parameters.FuncResult := 'Integer';

    // If eax is a var name it result.
    if rEax in Vars then
      RegNames[rEax] := 'Result';

    // Set the parameters.
    if rEcx in Params then
      ParamsStr := 'ParamrEax, ParamrEdx, ParamrEcx'
    else if rEdx in Params then
      ParamsStr := 'ParamrEax, ParamrEdx'
    else if rEax in Params then
      ParamsStr := 'ParamrEax';

    for I := 0 to StackParams -1 do
    begin
      if ParamsStr = '' then
        ParamsStr := 'StackParam' + IntToStr(I)
      else
        ParamsStr := ', StackParam' + IntToStr(I);
    end;

    if ParamsStr <> '' then
      ParamsStr := ParamsStr + ': Integer';

    // Create the proc header
    with TProc(Proc) do
      if ProcType in ptMethods then
        Strings.Add(Format(ProcDef[ProcType, Parameters.FuncResult <> ''],
            [AClass.AClass.ClassName, Name, Parameters.Parameters, Parameters.FuncResult]))
      else
        Strings.Add(Format(ProcDef[ProcType, Parameters.FuncResult <> ''], [Name, Parameters.Parameters, Parameters.FuncResult]));

    // create the vars.
    if Vars <> [] then
    begin
      Strings.Add('var');
      for Reg := Low(TRegister) to High(TRegister) do
        if Reg in Vars then
          Strings.Add(Format('  Var%s: Integer;', [GetEnumName(TypeInfo(TRegister), Integer(Reg))]));
    end;

    // Generate the real coce.
    Strings.Add('begin');
    with TPascalCallback.Create do
    try
      PascalRegNames := RegNames;
      PascalProc := TProc(Proc);
      // Decompile the assignment instructions.
      for I := 0 to Count -2 do
        Strings.Add(Format('  %s := %s;', [
           TAssignInstr(Items[I]).Target.AsPascal(Callback),
           TAssignInstr(Items[I]).Source.AsPascal(Callback)]));
    finally
      Free;
    end;

    // If eax is not already result, set result to eax.
    if RegNames[rEax] <> 'Result' then
      Strings.Add(Format('  Result := %s;', [RegNames[rEax]]));
    Strings.Add('end;');
    Result := True;
  except
    // Swallow EdcInstructionErrors and EDisAsmErrors, There is just no code generated.
    on EdcInstructionError do Strings.Clear;
    on EDisAsmError do Strings.Clear;
  end;
end;

procedure TdcInstructions.AddInstr(Instr: TInstruction);
begin
  FItems.Add(Instr);
  FChanged := True;
end;

end.

⌨️ 快捷键说明

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