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

📄 procs.pas

📁 SrcDecompiler is about creating a Delphi program decompiler. The program is written for Delphi 4 or
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    begin
      if FinaSize <> 0 then
        raise EDecompilerError.Create('There alredy is some fina code??');
      I := FindLastSimpleCallTo(TPEFileClass(PEFileClass).Units.SystemUnit.FindProcByName('@ClassDestroy').Address,
        Address, Size) - Address;
      if I <> -Integer(Address) then
      begin
        AfterFinaSize := Size - I - 5;
        FinaSize := 5;
        FHasClassDestroy := True;
      end;
    end;
  end;
  // Call the next event handler
  if Sender <> nil then
    Sender.CallNext(ProcSizeChange);
end;

{ TInitProcEnh }

constructor TInitProcEnh.CreateEnh(Proc: TProc);
begin
  inherited CreateEnh(Proc);
  Proc.OnInitSizeChange.Add(ProcInitSizeChange);
  Proc.OnSizeChange.Add(ProcInitSizeChange);
  ProcInitSizeChange(nil);
end;

destructor TInitProcEnh.Destroy;
begin
  Proc.OnSizeChange.Remove(ProcInitSizeChange);
  Proc.OnInitSizeChange.Remove(ProcInitSizeChange);
  inherited Destroy;
end;

procedure TInitProcEnh.ProcInitSizeChange(Sender: TmlneMethodList);
var
  AfterInitAddress: PChar;
  Table: PChar;
  J, K: Integer;
  PEFileClass: TPEFileClass;
begin
  if Proc.ImportInfo.Imported then Exit;
  PEFileClass := TPEFileClass(Proc.PEFileClass);
  AfterInitAddress := Proc.Address + Proc.BeforeInitSize + Proc.InitSize;
  // Check for init res string imort
  if (not FHasInitResStringImport) and
     (PEFileClass.StringInfos.Count <> 0) and
     (PEFileClass.VarInfos.Count <> 0) and
     (AfterInitAddress + 10 <= Proc.Address + Proc.ProcSize) and
     (AfterInitAddress[0] = #$B8) and
     (AfterInitAddress[5] = #$E8) and
     (TPEFileClass(PEFileClass).FindSystemProc(InitResStringImportsProcName) <> nil) and
     (PDWord(AfterInitAddress + 6)^ + AfterInitAddress + 10 = TPEFileClass(PEFileClass).FindSystemProc(InitResStringImportsProcName).Address) then
  begin
    Table := PPChar(AfterInitAddress + 1)^;
    // Create the vars.
    for J := 0 to PDWord(Table)^ -1 do
    begin
      // The assigend var.
      K := PEFileClass.VarInfos.IndexOfAddress(PPChar(Table + J * 8 + 4)^);
      if K = -1 then
        raise EDecompilerError.Create('Res string import var isn''t a var');
      PEFileClass.VarInfos[K].AUnit := Proc.AUnit;
      PEFileClass.VarInfos[K].AddDecomp(PEFileClass.StringInfos.FindString(PPChar(PPChar(Table + J * 8 +8)^)^),
        PPChar(Table + J * 8 + 4)^ - PEFileClass.VarInfos[K].Address, dtResString);
    end;
    // Create a Decomps the fill the block
    with TDecompItem.Create(PEFileClass.miscs) do
    begin
      Address := Table;
      RefAddress := Address;
      Size := PDWord(Table)^ * 8 + 4;
      Comments.Add('InitResStringImports Table filler');
    end;
    // Add the call the InitImports to the auto generated Code.
    {$IFOPT D+}
    SendDebug(Format('Found an init res string imports %p', [Pointer(Table)]));
    {$ENDIF}
    FHasInitResStringImport := True;
    Proc.InitSize := Proc.InitSize + 10;
    // Exit the proc because we are already called by changed the initsize.
    Exit;
  end;

  // Check for init import
  if (PEFileClass.FindSystemProc(InitImportsProcName) <> nil) and
     (not HasInitImport) and
     (PEFileClass.StringInfos.Count <> 0) and
     (PEFileClass.VarInfos.Count <> 0) and
     (AfterInitAddress + 10 <= Proc.Address + Proc.ProcSize) and
     (AfterInitAddress[0] = #$B8) and
     (AfterInitAddress[5] = #$E8) and
     (PDWord(AfterInitAddress + 6)^ + AfterInitAddress + 10 =
        PEFileClass.FindSystemProc(InitImportsProcName).Address) then
  begin
    Table := PPChar(AfterInitAddress + 1)^;
    // Apply the fixup
    asm
      mov  eax, Table
      call system.@InitImports
    end;
    // Create the vars.
    for J := 0 to PDWord(Table)^ -1 do
    begin
      K := PEFileClass.VarInfos.IndexOfAddress(PPChar(Table + J * 12 + 4)^);
      if K = -1 then
        raise EDecompilerError.Create('Address not in a var');
      PEFileClass.VarInfos[K].AUnit := Proc.AUnit;
      if PPChar(Table + J * 12 + 8)^ >= PEFileClass.Data then
      begin
        K := PEFileClass.VarInfos.IndexOfAddress(PPChar(Table + J*12 + 8)^);
        if K = -1 then
          raise EDecompilerError.Create('Address not in a var *');
        with PEFileClass.VarInfos[K] do
        begin
          Size := 4;
          Name := Format('!VarCorrector%p', [Pointer(Address)]);
          AUnit := Proc.AUnit;
          RefVar := True;
        end;
      end;
    end;
    // Create a Decomps the fill the block
    with TDecompItem.Create(PEFileClass.miscs) do
    begin
      Address := Table;
      RefAddress := Address;
      Size := PDWord(Table)^ * 12 + 4;
      Comments.Add('InitStringImports Table filler');
    end;
    // Add the call the InitImports to the auto generated Code.
    {$IFOPT D+}
    SendDebug(Format('Found an init imports %p', [Pointer(Table)]));
    {$ENDIF}
    FHasInitImport := True;
    Proc.InitSize := Proc.InitSize + 10;
    Exit;
  end;
  // Call the next event handler.
  if Sender <> nil then
    Sender.CallNext(ProcInitSizeChange);
end;

{ TInitProc }

constructor TInitProc.CreateInit(Procs: TProcs; Address: PChar);
var
  ASize: Integer;
begin
  inherited Create(Procs, Address);
  PossProcTypes := [ptInitialization];
  if (Address[0] = #$FF) and (Address[1] = #$25) then
  begin
    // This is an imported init proc.
    ProcSize := 0;
    Size := 8;
    Exit;
  end;
  ProcSize := GetProcSize(Address);
  Size := Align4(ProcSize);
  FinaSize := 1;
  // If Size > 8 a jnb must also be skipped.
  if Size > 8 then
  begin
    // The init code starts at sub dword Ptr [], $01; jnz ...
    while PWord(Address + FBeforeInitSize)^ <> $2D83 do
    begin
      Inc(FBeforeInitSize);
      if BeforeInitSize > Size then
        raise EDecompilerError.Create('Wrong Init section');
    end;
    with TDisAsm.Create do
    try
      GetInstruction(Address + BeforeInitSize + 7, ASize);
    finally
      Free;
    end;
    InitSize := 7 + ASize;
  end
  else
    InitSize := 7;
end;

constructor TInitProc.CreateFInit(Procs: TProcs; Address: PChar);
var
  ASize: Integer;
begin
  inherited Create(Procs, Address);
  PossProcTypes := [ptFinalization];
  if (Address[0] = #$FF) and (Address[1] = #$25) then
  begin
    // This is an imported FInit proc.
    ProcSize := 0;
    Size := 8;
    Exit;
  end;
  ProcSize := GetProcSize(Address);
  Size := Align4(ProcSize);
  if Size > $30 then
  begin
    with TDisAsm.Create do
    try
      GetInstruction(Address + $17, ASize);
    finally
      Free;
    end;
    InitSize := $17 + ASize;
  end
  else
    InitSize := $17;
  FinaSize := $17;
end;

{ TProcs }

constructor TProcs.CreateDecomp(PEFileClass: TPEFile);
begin
  inherited CreateDecomp(PEFileClass);
  FOnLoadPublishedMethods := TmlneMethodList.Create;
end;

destructor TProcs.Destroy; 
begin
  FOnLoadPublishedMethods.Free;
  inherited Destroy;
end;

procedure TProcs.LoadPublishedMethods;
var
  MethodTable: PMethodTable;
  MethodEntry: PMethodEntry;
  I, J: Integer;
  Proc: TProc;
begin
  with TPEFileClass(PEFileClass) do
    // Loop all the classes.
    for I := 0 to Classes.Count -1 do
      begin
        // Get the method table.
        MethodTable := GetMethodTable(Classes[I].AClass);
        if MethodTable <> nil then
          for J := 0 to MethodTable^.Count -1 do
          begin
            MethodEntry := GetMethodEntry(MethodTable, J);
            Proc := Procs.FindProc(MethodEntry^.Address);
            if Proc = nil then
              Proc := Procs.Add(MethodEntry^.Address);
            with Proc do
            begin
              Comments.Add('Published method');
              PossProcTypes := PossProcTypes * ptMethods;
              Name := MethodEntry^.Name;
              APublished := True;
              AClass := Classes[I];
            end;
          end;
      end;
  // Call the event handler
  FPublishedMethodsLoaded := True;
  FOnLoadPublishedMethods.CallFirst;
end;

procedure TProcs.LoadExportedProcs;
var
  I, J: Integer;
  Proc: TProc;
  AClassInfo: TClassInfo;
  InUnit: TUnit;
  NMInfo: TNameManglingInfo;
resourcestring
  SClassInExportNotFoundError = 'Class named %s mentioned in export not found';
begin
  with TPEFileClass(PEFileClass) do
    case ProjectType of
      ptDLL:
        // If this is a library assume all exported items are procs.
        for I := 0 to PEExports.Count -1 do
        begin
          Proc := FindProc(PEExports[I].Address);
          if Proc = nil then
            Proc := Add(PEExports[I].Address);
          with Proc do
          begin
            Comments.Add('Exported proc ' + PEExports[I].Name);
            PossProcTypes := [ptProcedure];
            IntfImpl := iiInterface;
            AppendBefore := atMayNot;
          end;
        end;
      ptPackage:
        begin
          for I := 0 to PEExports.Count -1 do
          begin
            NMInfo := GetNameManglingInfo(PEExports[I].Name);
            if NMInfo.NMType = eitClass then
            begin
              AClassInfo := TPEFileClass(PEFileClass).Classes.FindClass(TClass(PEExports[I].Address));
              if AClassInfo <> nil then
              begin
//                raise EDecompilerError.CreateFmt(SClassInExportNotFoundError, [NMInfo.ClassName]);
                AClassInfo.AUnit := Units.FindInUnitUsingFInit(PChar(AClassInfo.AClass));
                with TUnit(AClassInfo.AUnit) do
                begin
                  Name := NMInfo.UnitName;
                  Comments.Add('Unit name set because of export item ' + PEExports[I].Name);
                end;
              end;  
            end
            else if NMInfo.NMType = eitMethod then
            begin
              // Find the class.
              with TPEFileClass(PEFileClass).Units do
                AClassInfo := Items[FindByName(NMInfo.UnitName)].FindClassByName(NMInfo.ClassName);
              if AClassInfo = nil then
                raise EDecompilerError.CreateFmt(SClassInExportNotFoundError, [NMInfo.ClassName]);
            end
            else
              AClassInfo := nil;

            if (NMInfo.NMType in [eitProc, eitMethod]) and
               (NMInfo.ItemName <> 'initialization') then
            begin
              InUnit := Units.FindInUnitUsingFInit(PEExports[I].Address);
              InUnit.Name := NMInfo.UnitName;
              InUnit.Comments.Add('Unit name set because of export item ' + PEExports[I].Name);
              if (NMInfo.ItemName <> 'Finalization') then
              begin
                // Create the proc.
                Proc := FindProc(PEExports[I].Address);
                if Proc = nil then
                  Proc := Add(PEExports[I].Address);
                with Proc do
                begin
                  AUnit := InUnit;
                  Comments.Add('Exported proc ' + PEExports[I].Name);
                  if NMInfo.NMType = eitProc then
                  begin
                    PossProcTypes := [ptProcedure];
                    // move the proc the the interface part unless it is in the package unit
                    if TUnit(AUnit).UnitType <> utProgram then
                      IntfImpl := iiInterface;
                  end
                  else
                  begin
                    AClass := AClassInfo;
                    // there is no name it this is a constructor.
                    if NMInfo.ItemName = '' then
                      PossProcTypes := PossProcTypes * [ptConstructor, ptDestructor]
                    else
                      PossProcTypes := PossProcTypes * ptMethods;
                  end;
                  AppendBefore := atMayNot;
                  if Address <= Units.SystemUnit.FInit.Address then
                  begin
                    // Make it a proc of size 0 if it is in the system unit.
                    AppendAfter := atMayNot;
                    if NMInfo.ItemName <> '' then
                      Name := NMInfo.ItemName;
                  end
                  else
                    // there is no name it this is a constructor.
                    if NMInfo.ItemName <> '' then
                    begin
                      // If a proc with this name already exists add the address to the name.
                      J := FindProcByName(NMInfo.ItemName);
                      if (J = -1) or (Proc.Index = J) then
                        Name := NMInfo.ItemName
                      else
                        Name := Format('%s%p', [NMInfo.ItemName, Pointer(PEExports[I].Address)]);
                    end;
                  // Add the name including the methods as a comment.
                  Comments.Add(NMInfo.ItemProp);
                  // There are some strange procs in coride40.bpl which are in full capital
                  // Just thread them as proc markers (I don't known what else to do with them).
                  if NMInfo.ItemProp[1] = 'Q' then
                    AppendAfter := atMayNot;
                end;
              end;
            end;
          end;
        end;
    end;
end;

function TProcs.AnalyzeProc(Proc: TProc): Boolean;
var

⌨️ 快捷键说明

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