PluginFix v1.01[By BoB / Team PEiD]

===================================================================
// This simple tool converts OllyDbg and ImmuntiyDebugger plugins to be used with the new ImmDbg v1.80
// It needs to change the Imports and Exports of a plugin to do this, so it will NOT work on packed plugins!
===================================================================

//[ v1.01 ]
//
// Changes:
// o Fixed problem that if any section raw pointer was 0 then no dos/pe header written
// o Added support for OllyDbg Plugins
//=================================================================

Click here to download it(with src)~

Source Code:

======================================================================================================================
//
//  PluginFix v1.01
//  By BoB / Team PEiD
//
//======================================================================================================================
//
//  This simple tool converts OllyDbg and ImmuntiyDebugger plugins to be used with the new ImmDbg v1.80
//  It needs to change the Imports and Exports of a plugin to do this, so it will NOT work on packed plugins!
//
//=============================================================================================================[ v1.01 ]
//
//  Changes:
//    o  Fixed problem that if any section raw pointer was 0 then no dos/pe header written
//    o  Added support for OllyDbg Plugins
//
//======================================================================================================================


Program PluginFix;

{$APPTYPE CONSOLE}

Uses
  Windows;


//======================================================================================================================
// Conversion list of ordinals in order of old ImmDbg, containing ordinal in new v1.80 ..  $FF = Ignore ..

Const
  ExportCount = $FD;
  ExportTable : Array [1 .. ExportCount-1] Of Byte = (
    $03, $04, $05, $09, $0B, $0C, $0D, $0E, $10, $11, $12, $16, $1A, $1C, $1D, $1E,
    $1F, $20, $21, $22, $24, $25, $26, $28, $29, $2A, $2C, $2D, $2F, $30, $31, $32,
    $33, $34, $36, $38, $39, $3C, $3D, $3E, $40, $41, $42, $43, $44, $45, $46, $4D,
    $4E, $4F, $50, $51, $53, $55, $57, $59, $5A, $5C, $5D, $5F, $60, $61, $62, $65,
    $67, $68, $6A, $6C, $6E, $73, $76, $77, $78, $7A, $7D, $7F, $81, $82, $84, $89,
    $8B, $8C, $90, $91, $92, $94, $96, $98, $99, $9A, $9B, $9C, $9D, $A0, $A1, $A2,
    $A3, $A5, $CC, $CD, $CF, $D0, $D1, $D2, $D9, $DC, $DE, $E1, $E2, $E7, $E9, $EC,
    $ED, $EF, $F1, $F3, $F5, $3F, $48, $4A, $74, $75, $93, $D6, $D8, $14, $1B, $23,
    $2B, $2E, $3B, $47, $49, $4B, $4C, $52, $54, $58, $5B, $63, $64, $66, $69, $6B,
    $6D, $6F, $70, $79, $7B, $7C, $83, $85, $87, $8A, $95, $A4, $CE, $D4, $D5, $DF,
    $EA, $EB, $F4, $06, $15, $17, $18, $19, $27, $35, $80, $DA, $E0, $E4, $3A, $56,
    $72, $88, $EE, $0A, $13, $E5, $E6, $5E, $DD, $8E, $E8, $08, $9E, $CA, $07, $C6,
    $C4, $C2, $D7, $B9, $BA, $BC, $FF, $F0, $C7, $BF, $B7, $7E, $FF, $B6, $B4, $C0,
    $C5, $B8, $A6, $AB, $B3, $F2, $FF, $D3, $8D, $BE, $B5, $71, $C3, $01, $A9, $FF,
    $C9, $AD, $B1, $A8, $F7, $AA, $AF, $BD, $C1, $F8, $8F, $37, $AE, $FF, $9F, $E3,
    $CB, $BB, $86, $0F, $B0, $AC, $DB, $FF, $97, $FF, $00, $B2
  );


//======================================================================================================================

Type
  TMemRec = Packed Record
    Address : Pointer;
    Size    : DWord;
  End;

  PImageSectionHeader = ^TImageSectionHeader;
  TImageSectionHeader = Packed Record
    Name                 : Array [1 .. 8] Of Char;
    VirtualSize          : DWord;
    VirtualRva           : DWord;
    RawSize              : DWord;
    RawOffset            : DWord;
    Unused               : Array [1 .. 3] Of DWord;  // Depreciated / Coff only ..
    Characteristics      : DWord;
  End;

  PImageImportDescriptor = ^TImageImportDescriptor;
  TImageImportDescriptor = Packed Record
    OriginalFirstThunk, TimeDateStamp,
    ForwarderChain, Name,
    FirstThunk: DWord;
  End;

  PImageExportDirectory = ^TImageExportDirectory;
  TImageExportDirectory = Packed Record
    Characteristics, TimeDateStamp: DWord;
    MajorVersion, MinorVersion: Word;
    Name, Base, NumberOfFunctions,
    NumberOfNames, RvaOfFunctions,
    RvaOfNames, RvaOfNameOrdinals: DWord;
  End;


//======================================================================================================================
// Useful functions ..

Function  Ptr(Const P : Pointer; Const Offset : Integer) : Pointer;
Begin
  Result := Pointer(Int64(P) + Offset);
End;

Function  ALIGN_DOWN(Const a, b : DWord) :  DWord;
Begin
  Result := a;
  If (a <> 0) And (b <> 0) Then Result := ((a Div b) * b);
End;

Function  ALIGN_UP(Const a, b : DWord) :  DWord;
Begin
  Result := ALIGN_DOWN(a + (b - 1), b);
End;

Function  IntToStr(Const Value : DWord) : String;
Begin
  Str(Value, Result);
End;

Function  StrLen(Const PC : PChar) : DWord;
Begin
  Result := 0;
  While (PC[Result] <> #0) Do Inc(Result);
End;

Function  UpperCase(Const S: String): String;
Var
  I, L : DWord;
Begin
  L := Length(S);
  SetLength(Result, L);
  If (L > 0) Then For I := 1 To L Do Result[I] := UpCase(S[I]);
End;

Function  AllocMem(Const Size : DWord) : Pointer;
Begin
  GetMem(Result, Size);
  ZeroMemory(Result, Size);
End;




//======================================================================================================================
// Load and map a PE file as an image ..

Function  LoadFileAsImage(Const Filename : String) : PImageDosHeader;
Var
  hFile, I, Size, Attr : DWord;
  Raw : Pointer;

  // Map a raw module to image ..  MUST be Valid PE, cos only basic testing done!
  Function  MapRawPE(Const RawMem : Pointer; Const Size : DWord) : TMemRec;
  Var
    Dos : PImageDosHeader Absolute RawMem;
    NT  : PImageNtHeaders;
    Sec : PImageSectionHeader;
    Mem : Pointer;
    Idx : DWord;
    Val : DWord;
  Begin
    Result.Address := Nil;
    Result.Size := 0;
    If IsBadReadPtr(RawMem, Size) Or (Dos^.e_magic <> IMAGE_DOS_SIGNATURE) Then Exit;
    NT := Ptr(RawMem, Dos^._lfanew);
    If (NT^.Signature <> IMAGE_NT_SIGNATURE) Then Exit;
    // Allocate 1 page more so it's possible to enlarge the image without reallocating ..
    Val := Align_Up(NT^.OptionalHeader.SizeOfImage + $1000, NT^.OptionalHeader.SectionAlignment);
    Mem := VirtualAlloc(Nil, Val, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    Result.Address := Mem;
    If (Mem = Nil) Then Exit;
    // Copy section data ..
    Sec := Ptr(NT, 4 + SizeOf(TImageFileHeader) + NT^.FileHeader.SizeOfOptionalHeader);
    Val := Size;
    Idx := 0;
    While (Idx < NT^.FileHeader.NumberOfSections) Do Begin
      If (Sec^.RawOffset > 0) Then Begin
        CopyMemory(Ptr(Mem, Sec^.VirtualRva), Ptr(RawMem, Sec^.RawOffset), Sec^.RawSize);
        If (Sec^.RawOffset < Val) Then Val := Sec^.RawOffset;  // Val = Lowest Raw offset ..
      End;
      Inc(Sec);
      Inc(Idx);
    End;
    // Copy all headers ..
    CopyMemory(Mem, RawMem, Val);
  End;

Begin
  Result := Nil;
  Raw := Nil;
  // Get/Set Attr so we can read hidden / read only files ..
  Attr := GetFileAttributes(PChar(Filename));
  If (Attr <> $FFFFFFFF) Then Try
    SetFileAttributes(PChar(Filename), FILE_ATTRIBUTE_NORMAL);
    hFile := CreateFile(PChar(Filename), GENERIC_READ, FILE_SHARE_READ, Nil, Open_Existing, FILE_ATTRIBUTE_NORMAL, 0);
    If (hFile <> INVALID_HANDLE_VALUE) Then Try
      Size := GetFileSize(hFile, Nil);
      Raw := AllocMem(Size);
      ReadFile(hFile, Raw^, Size, I, Nil);
      Result := MapRawPE(Raw, I).Address;
    Finally
      CloseHandle(hFile);
      FreeMem(Raw);
    End;
  Finally
    SetFileAttributes(PChar(Filename), Attr);
  End;
End;


//======================================================================================================================
// Save a mapped module to raw image file ..

Procedure SaveModuleToRawFile(Const Module : PImageDosHeader; Const Filename : String);
Var
  Mem : TMemRec;

  // Save a mapped module to raw image memory block ..
  Function  BuildRawPEFromModule : TMemRec;
  Var
    NT  : PImageNtHeaders;
    Sec : PImageSectionHeader;
    I,J : DWord;
  Begin
    Result.Address := Nil;
    Result.Size := 0;
    If IsBadReadPtr(Module, SizeOf(TImageDosHeader)) Or (Module^.e_magic <> IMAGE_DOS_SIGNATURE) Then Exit;
    NT := Ptr(Module, Module^._lfanew);
    If (NT^.Signature <> IMAGE_NT_SIGNATURE) Then Exit;

    // Calc raw size ..
    Sec := Ptr(NT, 4 + SizeOf(TImageFileHeader) + NT^.FileHeader.SizeOfOptionalHeader);
    Result.Size := Sec^.RawOffset;
    J := NT^.OptionalHeader.SizeOfImage;
    I := 0;
    While (I < NT^.FileHeader.NumberOfSections) Do Begin
      If (Sec^.RawOffset < J) And (Sec^.RawOffset > 0) Then J := Sec^.RawOffset;  // J = Lowest Raw offset ..
      Inc(Result.Size, Align_up(Sec^.RawSize, NT^.OptionalHeader.FileAlignment));
      Inc(Sec);
      Inc(I);
    End;

    // Alloc mem and build Raw image ..
    Result.Address := AllocMem(Result.Size);
    CopyMemory(Result.Address, Module, J);
    Sec := Ptr(NT, 4 + SizeOf(TImageFileHeader) + NT^.FileHeader.SizeOfOptionalHeader);
    I := 0;
    While (I < NT^.FileHeader.NumberOfSections) Do Begin
      CopyMemory(Ptr(Result.Address, Sec^.RawOffset), Ptr(Module, Sec^.VirtualRva), Sec^.RawSize);
      Inc(Sec);
      Inc(I);
    End;
  End;

  // Save memory block to file ..
  Procedure SaveMemToFile(Const Mem : TMemRec; Const Filename : String);
  Var
    hFile, I : DWord;
  Begin
    If (Mem.Address = Nil) Or (Mem.Size = 0) Then Exit;
    If SetFileAttributes(PChar(Filename), FILE_ATTRIBUTE_NORMAL) Then DeleteFile(PChar(Filename));
    hFile := CreateFile(PChar(Filename), GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ, Nil, Create_Always, FILE_ATTRIBUTE_NORMAL, 0);
    If (hFile = INVALID_HANDLE_VALUE) Then Exit;
    Try
      WriteFile(hFile, Mem.Address^, Mem.Size, I, Nil);
      FlushFileBuffers(hFile);
    Finally
      CloseHandle(hFile);
    End;
  End;

Begin
  Mem := BuildRawPEFromModule;
  SaveMemToFile(Mem, Filename);
  FreeMem(Mem.Address);
End;


//======================================================================================================================
// Fix the imports and exports of a plugin ..

Procedure FixPlugin(Const Filename : String);
Const
  ImmDbg = 'ImmunityDebugger.Exe';
Var
  Dos : PImageDosHeader;
  NT  : PImageNtHeaders;
  Sec : PImageSectionHeader;
  Ex  : PImageExportDirectory;
  Imp : PImageImportDescriptor;
  PC  : PAnsiChar;
  PD  : PDWord;
  I   : DWord;
  NoIm: Boolean;
  Name: String;
  Size: DWord;
  Rva : DWord;

  // Fix an import thunk for ImmunityDebugger.exe ..
  Procedure FixThunk(Const Thunk : DWord);
  Var
    J : DWord;
  Begin
    If (Thunk > 0) Then Begin
      PD := Ptr(Dos, Thunk);
      If IsBadReadPtr(PD, 4) Or (PD^ = 0) Then Exit;
      While (PD^ <> 0) Do Begin
        If (PD^ And $80000000 <> 0) Then Begin
          // Change old ordinal to new ordinal value ..
          J := PD^ And $0FFF;
          WriteLn('    #' + IntToStr(J) + ' -> #' + IntToStr(ExportTable[J]));
          PD^ := (ExportTable[J] Or $80000000);
          NoIm := False;
        End Else Begin
          // Fix imported name string by skipping underscore in name ..
          PC := Ptr(Dos, PD^ + 2);
          If (Not IsBadReadPtr(PC, 4)) And (PC^ = '_') Then Begin
            PWord(Ptr(Dos, PD^))^ := 0;
            Write('    ' + PC + ' -> ');
            PC^ := #0;
            Inc(PD^);
            NoIm := False;
            Inc(PC);
            WriteLn(PC);
          End;
        End;
        Inc(PD);
      End;
    End;
  End;

Begin
  // Load and map plugin dll as image ..
  Dos := LoadFileAsImage(Filename);
  If (Dos <> Nil) Then Try
    WriteLn('Processing ' + Filename);

    // Find export names ..
    NT := Ptr(Dos, Dos^._lfanew);
    Ex := Ptr(Dos, NT^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    PD := Ptr(Dos, Ex.RvaOfNames);

    // Find size of empty space needed to write new export strings ..
    I := 0;
    Rva := 0;
    Size := 0;
    While (I < Ex^.NumberOfNames) Do Begin
      PC := Ptr(Dos, PD^);
      If IsBadReadPtr(PC, 4) Then Begin
        WriteLn('    Error reading export string!');
        Exit;
      End;
      If ((PC^ = '_') And (PC[5] = '_')) Then Inc(Size, 3 + StrLen(PC));
      Inc(I);
      Inc(PD);
    End;
    // Fixup image for adding OllyDbg strings..
    If (Size > 0) Then Begin
      Sec := Ptr(NT, 4 + SizeOf(TImageFileHeader) + NT^.FileHeader.SizeOfOptionalHeader + ((NT^.FileHeader.NumberOfSections - 1) * SizeOf(TImageSectionHeader)));
      Rva := Align_Up(Sec^.VirtualRva + Sec^.RawSize, NT^.OptionalHeader.FileAlignment);
      While (PDWord(DWord(Dos) + Rva)^ = 0) Do Dec(Rva, 4);
      Rva := Align_Up(Rva + 12, 16);
      Sec^.RawSize := Align_Up((Rva - Sec^.VirtualRva) + Size + StrLen(ImmDbg) + 1, NT^.OptionalHeader.FileAlignment);
      Sec^.VirtualSize := Align_Up(Sec^.RawSize, NT^.OptionalHeader.SectionAlignment);
      NT^.OptionalHeader.SizeOfImage := Sec^.VirtualRva + Sec^.VirtualSize;
    End;

    // Fix exports ..
    WriteLn('  Fixing Exports');
    PD := Ptr(Dos, Ex.RvaOfNames);
    I := 0;
    While (I < Ex^.NumberOfNames) Do Begin
      PC := Ptr(Dos, PD^);
      If ((PC^ = '_') And (PC[1] <> '_')) Then Begin
        Write('    ' + PC + ' -> ');
        // Check for Olly export ..
        If (PC[5] = '_') Then Begin
          // Add new export string ..
          PD^ := Rva;
          Inc(PC, 5);
          Move('IMMDBG', Ptr(Dos, Rva)^, 6);
          Move(PC^, Ptr(Dos, Rva + 6)^, StrLen(PC));
          Inc(Rva, 7 + StrLen(PC));
        End Else
          Inc(PD^);  // Fix for old ImmDbg is simpler .. :)
        PC := Ptr(Dos, PD^);
        WriteLn(PC);
      End;
      Inc(I);
      Inc(PD);
    End;
    WriteLn;

    // Fix imports ..
    NoIm := True;
    WriteLn('  Fixing Imports');
    Imp := Ptr(Dos, NT^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    While (Imp^.Name <> 0) Do Begin
      PC := Ptr(Dos, Imp^.Name);
      If IsBadReadPtr(PC, Length(ImmDbg)) Then Begin
        WriteLn('    Error reading imported Dll string!');
        Exit;
      End;
      // Importing from an EXE ?
      If (Uppercase(Copy(PC, StrLen(PC) - 3, 4)) = '.EXE') Then Begin
        If (Uppercase(Copy(PC, 1, 8)) <> 'IMMUNITY') Then Begin
          // If OllyDbg then imported module name needs to be fixed to ImmunityDebugger.EXE ..
          Move(ImmDbg, Ptr(Dos, Rva)^, Length(ImmDbg));
          Imp^.Name := Rva;
        End;
        // Convert the import thunks ..
        FixThunk(Imp^.OriginalFirstThunk);
        FixThunk(Imp^.FirstThunk);
      End;
      Inc(Imp);
    End;
    If NoIm Then WriteLn('Warning: No Imports were processed!');
    WriteLn;

    // Build new plugin raw file ..
    I := Length(FileName);
    While (FileName[I] <> '.') Do Dec(I);
    Name := Copy(Filename, 1, I-1) + '_Fixed.DLL';
    SaveModuleToRawFile(Dos, Name);
    WriteLn('Saved as ' + Name);

  Finally
    VirtualFree(Dos, 0, MEM_RELEASE);
    WriteLn;
    WriteLn;
  End;
End;


//======================================================================================================================

Procedure Main;
Var
  I : DWord;
Begin
  If (ParamCount = 0) Then WriteLn('Usage: Drop one or more plugin DLLs onto this exe to fix them')
  Else For I := 1 To ParamCount Do FixPlugin(ParamStr(I));
End;


//======================================================================================================================

Begin
  WriteLn('PluginFix v1.01');
  WriteLn('Simple Tool to convert OllyDbg and ImmDbg plugins for use with ImmDbg v1.80');
  WriteLn('By BoB -> Team PEiD');
  WriteLn;

  Main;

  Write('Press ENTER');
  ReadLn;
End.
☆版权☆

* 网站名称:obaby@mars
* 网址:https://oba.by/
* 个性:https://oba.by/
* 本文标题: 《PluginFix v1.01[By BoB / Team PEiD]》
* 本文链接:https://oba.by/2011/02/2510
* 短链接:https://oba.by/?p=2510
* 转载文章请标明文章来源,原文标题以及原文链接。请遵从 《署名-非商业性使用-相同方式共享 2.5 中国大陆 (CC BY-NC-SA 2.5 CN) 》许可协议。


You may also like

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注