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

📄 disasm.pas

📁 用delphi实现反汇编测控专家 用于各个行业的高技术仪表
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit DisAsm;

interface

uses
    SysUtils, Classes;

type
    EDisAsmError = class(Exception);
    TRegister = (rEax, rEcx, rEdx, rEbx, rEsp, rEbp, rEsi, rEdi);
    TdaRef = record
      MultiplyReg1: Integer;
      ARegister1: TRegister;
      MultiplyReg2: Integer;
      ARegister2: TRegister;
      Immidiate: PChar;
    end;

    TJumpInstrProc = Procedure (Param: Pointer; ValueAddress, JumpAddress: PChar; var Result: String);
    TCallInstrProc = Procedure (Param: Pointer; ValueAddress, CallAddress: PChar; var Result: String);
    TAddressRefProc = Procedure (Param: Pointer; ValueAddress, RefAddress: PChar; var Result: String);
    TRefProc = Procedure (Param: Pointer; Ref: TdaRef; RefSize: Integer; var Result: String);
    TImmidiateDataProc = Procedure (Param: Pointer; ValueAddress: PChar; OperandSize: Integer; Sigend: Boolean; var Result: String);

    TDisAsm = class(TObject)
    public
      OnJumpInstr: TJumpInstrProc;
      OnCallInstr: TCallInstrProc;
      OnAddressRef: TAddressRefProc;
      OnRef: TRefProc;
      OnImmidiateData: TImmidiateDataProc;
      Param: Pointer;
      function GetInstruction(Address: PChar; var Size: Integer): String;
    end;

const
     ModRMReg = $38;
     ModRMMod = $C0;  
     ModRMRM =  $07;
     ERROR_NOT_ENOUGH_CODE = 'Not enough code.';
     ERROR_INVALID_OPERAND = 'Invalid AddrMethod and OperandType combination';
     ERROR_INVALID_OPERAND_SIZE = 'Invalid OperandSize';

function SignedIntToHex(Value: Integer; Digits: Integer): String;
function FindFirstSimpleCallTo(CallAddress, SearchAddress: PChar; SearchSize: Integer): PChar;
function FindLastSimpleCallTo(CallAddress, SearchAddress: PChar; SearchSize: Integer): PChar;

implementation

uses
    Windows, DisAsmTables;

function SignedIntToHex(Value: Integer; Digits: Integer): String;
begin
     if Value < 0 then Result := '-$' + IntToHex(-Integer(Value), Digits)
                  else Result := '+$' + IntToHex(Integer(Value), Digits);
end;

function FindFirstSimpleCallTo(CallAddress, SearchAddress: PChar; SearchSize: Integer): PChar;
begin
     Result := SearchAddress;
     While Result <= SearchAddress + SearchSize - 5 do
           begin
                if (Result[0] = #$E8) and (Result + PInteger(Result + 1)^ + 5 = CallAddress) then
                   Exit;
                Inc(Result);
           end;
     Result := nil;
end;

function FindLastSimpleCallTo(CallAddress, SearchAddress: PChar; SearchSize: Integer): PChar;
begin
     Result := SearchAddress + SearchSize - 5;
     While Result >= SearchAddress  do
           begin
                if (Result[0] = #$E8) and (Result + PInteger(Result + 1)^ + 5 = CallAddress) then
                   Exit;
                Dec(Result);
           end;
     Result := nil;
end;

function TDisAsm.GetInstruction(Address: PChar; var Size: Integer): String;
var
   Ref: TdaRef;

   function ReadDWord: DWord;
   begin
        if IsBadReadPtr(Address, 4) then
           Raise EDisAsmError.Create(ERROR_NOT_ENOUGH_CODE);
        Result := PDWord(Address + Size)^;
        Inc(Size, 4);
   end;

   function ReadWord: Word;
   begin
        if IsBadReadPtr(Address, 2) then
           Raise EDisAsmError.Create(ERROR_NOT_ENOUGH_CODE);
        Result := PWord(Address + Size)^;
        Inc(Size, 2);
   end;

   function ReadByte: Byte;
   begin
        if IsBadReadPtr(Address, 1) then
           Raise EDisAsmError.Create(ERROR_NOT_ENOUGH_CODE);
        Result := PByte(Address + Size)^;
        Inc(Size, 1);
   end;

   function GetRefAddress: String;
   var
      RefAddress: PChar;
   begin
        RefAddress := PChar(ReadDWord);
        Ref.Immidiate := Ref.Immidiate + Integer(RefAddress);
        Result := '$' + IntToHex(DWord(RefAddress), 4);
        if Assigned(OnAddressRef) then
           OnAddressRef(Param, Address + Size - 4, RefAddress, Result);
        Result := '^' + Chr(Length(Result)) + Result;
   end;

var
   XHasModRM: Boolean;
   XModRM: Byte;

   function ModRM: Byte;
   begin
        if not XHasModRM then
           begin
                XModRM := ReadByte;
                XHasModRM := True;
           end;
        Result := XModRM;
   end;

var
   XHasSib: Boolean;
   XSib: Byte;

   function Sib: Byte;
   begin
        if not XHasSib then
           begin
                XSib := ReadByte;
                XHasSib := True;
           end;
        Result := XSib;
   end;

var
   DeffOperandSize: Integer;
   AddressSize: Integer;
   OperandSize: Integer;
   SegOverride: Boolean;
   SegName: String;
   MustHaveSize: Boolean;

   function Operand(AddrMethod, OperandType, EnhOperandType: Char): String;

      function GetRegName(Reg: Byte): String;
      const
           ByteRegs1: array[0..3] of Char = 'acdb';
           ByteRegs2: array[0..1] of Char = 'lh';
           WordRegs1: array[0..7] of Char = 'acdbsbsd';
           WordRegs2: array[0..4] of Char = 'xxpi';
      begin
           if OperandSize = 1 then
              Result := ByteRegs1[Reg mod 4] + ByteRegs2[Reg div 4]
              else
              begin
                   if OperandSize = 4 then Result := 'e'
                                      else Result := '';
                   Result  := Result + WordRegs1[Reg] + WordRegs2[Reg div 2];
              end;
      end;

      function GetEffectiveAddress(EAMustHaveSize: Boolean): String;
      var
         RM: Byte;
         AMod: Byte;

         function ReadSib: String;
         var
            SI: Byte;
            SS: Byte;
            Base: Byte;
         begin
              Base := Sib and $07;        
              SI := (Sib shr 3) and $07;  
              SS := (Sib shr 6) and $03;
              Case Base of
                0: Result := '[eax';
                1: Result := '[ecx';
                2: Result := '[edx';
                3: Result := '[ebx';
                4: Result := '[esp';
                5: if AMod <> 0 then Result := '[ebp'
                                else Result := '[' + GetRefAddress;
                6: Result := '[esi';
                7: Result := '[edi';
              end;
              if (Base <> 5) or (AMod = 0) then
                 begin
                      Ref.ARegister2 := TRegister(Base);
                      Ref.MultiplyReg2 := 1;
                 end;
              Case SI of
                0: Result := Result + '+eax';
                1: Result := Result + '+ecx';
                2: Result := Result + '+edx';
                3: Result := Result + '+ebx';
                5: Result := Result + '+ebp';
                6: Result := Result + '+esi';
                7: Result := Result + '+edi';
              end;
              if SI <> 4 then Ref.ARegister1 := TRegister(SI);
              if SI <> 4 then
                 Case SS of
                   0: begin
                           Result := Result + '';
                           Ref.MultiplyReg1 := 1;
                      end;
                   1: begin
                           Result := Result + '*2';
                           Ref.MultiplyReg1 := 2;
                      end;
                   2: begin
                           Result := Result + '*4';
                           Ref.MultiplyReg1 := 4;
                      end;
                   3: begin
                           Result := Result + '*8';
                           Ref.MultiplyReg1 := 8;
                      end;
                 end;
         end;

      var
         I: Integer;
      begin
           RM := ModRM and ModRMRM;
           AMod := ModRm and ModRMMod shr 6;
           if AMod = 3 then
              begin
                   Result := GetRegName(RM);
                   Exit;
              end;
           Result := '%s' + Chr(OperandSize);
           if SegOverride then
           Result := Result + SegName + ':';
           if OperandSize <> 4 then
           MustHaveSize := True;
           if AddressSize = 4 then
              begin
                   if (AMod = 0) and (RM = 5) then
                      begin
                           Result := Result + '[' + GetRefAddress + ']';
                           if Assigned(OnRef) then OnRef(Param, Ref, OperandSize, Result);
                           Exit;
                      end;
              end
              else
              begin
                   if (AMod = 0) and (RM = 6) then
                      begin
                           Result := Result + '[' + GetRefAddress + ']';
                           if Assigned(OnRef) then OnRef(Param, Ref, OperandSize, Result);
                           Exit;
                      end;
              end;
           if AddressSize = 2 then
              Case RM of
                0: Result := Result + '[bx+si';

⌨️ 快捷键说明

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