Penulis Topik: [Delphi] PEB Module Manipulation  (Dibaca 8061 kali)

Offline meong

  • Pro100
  • ****
  • Tulisan: 121
  • Reputation: 203
    • Lihat Profil
[Delphi] PEB Module Manipulation
« pada: Juni 11, 2011, 04:04:19 PM »
just some function for manipulate module in PEB...

Kode: [Pilih]
{ U_PEBModule
Author: Abhe
Description: Some manipulation Routine In PEB Ldr Data
Release Date: 23th april 2011
Website: http://cybercoding.wordpress.com/
}
unit U_PEBModule;

interface
uses
  windows,
  sysutils,
  JwaNative,
  JwaNtStatus,
  NcxNtTeb,
  NcxNtDef;

Procedure EnumPeb(ph:Thandle);
Function RemoteModuleHandle(ph : THandle; Modulename: PWidechar):DWord;
Function RemoteModuleImageName(ph,Mh : THandle):WideString;
Procedure RemotePatchModuleFileName(ph,mh : THandle; NewModulename: PWidechar);
Procedure UnlinkModule(ph,mh : THandle);
implementation

type
  PROCESS_BASIC_INFORMATION = record
    ExitStatus: Cardinal;
    PebBaseAddress: PVOID;
    AffinityMask: Cardinal;
    BasePriority: Cardinal;
    UniqueProcessId: Cardinal;
    InheritedFromUniqueProcessId: Cardinal;
  end;
  TProcessBasicInformation = PROCESS_BASIC_INFORMATION;
  PProcessBasicInformation = ^TProcessBasicInformation;

function NtSuccess(AStatus: Longint): Boolean;
begin
  Result := AStatus >= 0;
end;

Procedure EnumPeb(ph:Thandle);
var
  pbi           : PROCESS_BASIC_INFORMATION;
  PEB           : TPeb32;
  LdrData       : TPebLdrData32;
  LdrModule     : TLdrDataTableEntry32;
  i, dwread     : DWord;
  Head,Current  : DWord;
  BaseDllName   : array[0..MAX_PATH] of widechar;
begin

  {Get PROCESS_BASIC_INFORMATION}
  if not NtSuccess(ZwQueryInformationProcess(ph,ProcessBasicInformation,@pbi,SizeOf(pbi),@dwread)) then begin
    OutputDebugString(Pchar('Failed Get PEB Location : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {Reading PEB}
  if not NtSuccess(ZwReadVirtualMemory(ph,pbi.PebBaseAddress,@PEB,sizeof(PEB),@dwread)) then begin
    OutputDebugString(Pchar('Failed Reading PEB : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {Reading LoaderData}
  if not NtSuccess(ZwReadVirtualMemory(ph,PEB.Ldr,@LdrData,sizeof(LdrData),@dwread)) then begin
    OutputDebugString(Pchar('Failed Reading LdrData : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {init for enum the linked list}
  i := 0;
  Head := 0;
  Current := DWord(LdrData.InLoadOrderModuleList.Flink);

  { loop for all ldr entry or module }
  repeat

    {Reading Current entry}
    if not NtSuccess(ZwReadVirtualMemory(ph,Ptr(Current),@LdrModule,sizeof(LdrModule),@dwread)) then begin
      OutputDebugString(Pchar('Failed Reading Current Module : '+SysErrorMessage(Getlasterror)));
      break;
    end;

    {Reading BaseDllName}
    Fillchar(BaseDllName,sizeof(BaseDllName),0);
    if not NtSuccess(ZwReadVirtualMemory(ph,LdrModule.BaseDllName.Buffer,@BaseDllName,LdrModule.BaseDllName.Length,@dwread)) then begin
      OutputDebugString(Pchar('Failed Reading BaseDllName : '+SysErrorMessage(Getlasterror)));
    end;
    OutputDebugString(BaseDllName);

    {Next Module}
    if i=0 then Head := Dword(LdrModule.InLoadOrderLinks.Blink);
    Current := Dword(LdrModule.InLoadOrderLinks.Flink);
    inc(i);
  until Current = Head;
end;

Function RemoteModuleHandle(ph : THandle; Modulename: PWidechar):DWord;
var
  pbi           : PROCESS_BASIC_INFORMATION;
  PEB           : TPeb32;
  LdrData       : TPebLdrData32;
  LdrModule     : TLdrDataTableEntry32;
  i, dwread     : DWord;
  Head,Current  : DWord;
  BaseDllName   : array[0..MAX_PATH] of widechar;
begin
  result := 0;

  {Get PROCESS_BASIC_INFORMATION}
  if not NtSuccess(ZwQueryInformationProcess(ph,ProcessBasicInformation,@pbi,SizeOf(pbi),@dwread)) then begin
    OutputDebugString(Pchar('Failed Get PEB Location : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {Reading PEB}
  if not NtSuccess(ZwReadVirtualMemory(ph,pbi.PebBaseAddress,@PEB,sizeof(PEB),@dwread)) then begin
    OutputDebugString(Pchar('Failed Reading PEB : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {Reading LoaderData}
  if not NtSuccess(ZwReadVirtualMemory(ph,PEB.Ldr,@LdrData,sizeof(LdrData),@dwread)) then begin
    OutputDebugString(Pchar('Failed Reading LdrData : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {init for enum the linked list}
  i := 0;
  Head := 0;
  Current := DWord(LdrData.InLoadOrderModuleList.Flink);

  { loop for all ldr entry or module }
  repeat

    {Reading Current entry}
    if not NtSuccess(ZwReadVirtualMemory(ph,Ptr(Current),@LdrModule,sizeof(LdrModule),@dwread)) then begin
      OutputDebugString(Pchar('Failed Reading Current Module : '+SysErrorMessage(Getlasterror)));
      break;
    end;

    {Reading BaseDllName}
    Fillchar(BaseDllName,sizeof(BaseDllName),0);
    if not NtSuccess(ZwReadVirtualMemory(ph,LdrModule.BaseDllName.Buffer,@BaseDllName,LdrModule.BaseDllName.Length,@dwread)) then begin
      OutputDebugString(Pchar('Failed Reading BaseDllName : '+SysErrorMessage(Getlasterror)));
    end;

    {Check if this our target}
    if (StrComp(LdrModule.BaseDllName.Buffer,Modulename) = 0) then begin
      result := DWord(LdrModule.DllBase);
      OutputDebugString(pchar(inttohex(result,8)));
      break;
    end;

    {Next Module}
    if i=0 then Head := Dword(LdrModule.InLoadOrderLinks.Blink);
    Current := Dword(LdrModule.InLoadOrderLinks.Flink);
    inc(i);
  until Current = Head;
end;

Function RemoteModuleImageName(ph,Mh : THandle):WideString;
var
  pbi           : PROCESS_BASIC_INFORMATION;
  PEB           : TPeb32;
  LdrData       : TPebLdrData32;
  LdrModule     : TLdrDataTableEntry32;
  i, dwread     : DWord;
  Head,Current  : DWord;
  BaseDllName   : array[0..MAX_PATH] of widechar;
begin
  result := '';

  {Get PROCESS_BASIC_INFORMATION}
  if not NtSuccess(ZwQueryInformationProcess(ph,ProcessBasicInformation,@pbi,SizeOf(pbi),@dwread)) then begin
    OutputDebugString(Pchar('Failed Get PEB Location : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {Reading PEB}
  if not NtSuccess(ZwReadVirtualMemory(ph,pbi.PebBaseAddress,@PEB,sizeof(PEB),@dwread)) then begin
    OutputDebugString(Pchar('Failed Reading PEB : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {Reading LoaderData}
  if not NtSuccess(ZwReadVirtualMemory(ph,PEB.Ldr,@LdrData,sizeof(LdrData),@dwread)) then begin
    OutputDebugString(Pchar('Failed Reading LdrData : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {init for enum the linked list}
  i := 0;
  Head := 0;
  Current := DWord(LdrData.InLoadOrderModuleList.Flink);

  { loop for all ldr entry or module }
  repeat

    {Reading Current entry}
    if not NtSuccess(ZwReadVirtualMemory(ph,Ptr(Current),@LdrModule,sizeof(LdrModule),@dwread)) then begin
      OutputDebugString(Pchar('Failed Reading Current Module : '+SysErrorMessage(Getlasterror)));
      break;
    end;

    {Check if this our target}
    if (DWord(LdrModule.DllBase) = mh) then begin

      {Reading BaseDllName}
      Fillchar(BaseDllName,sizeof(BaseDllName),0);
      if not NtSuccess(ZwReadVirtualMemory(ph,LdrModule.BaseDllName.Buffer,@BaseDllName,LdrModule.BaseDllName.Length,@dwread)) then begin
        OutputDebugString(Pchar('Failed Reading BaseDllName : '+SysErrorMessage(Getlasterror)));
      end;

      result := BaseDllName;
      OutputDebugString(BaseDllName);
      break;
    end;

    {Next Module}
    if i=0 then Head := Dword(LdrModule.InLoadOrderLinks.Blink);
    Current := Dword(LdrModule.InLoadOrderLinks.Flink);
    inc(i);
  until Current = Head;
end;

Procedure RemotePatchModuleFileName(ph,mh : THandle; NewModulename: PWidechar);
var
  pbi           : PROCESS_BASIC_INFORMATION;
  PEB           : TPeb32;
  LdrData       : TPebLdrData32;
  LdrModule     : TLdrDataTableEntry32;
  i, dwread     : DWord;
  Head,Current  : DWord;
  pNewAddr      : Pointer;
begin

  {Get PROCESS_BASIC_INFORMATION}
  if not NtSuccess(ZwQueryInformationProcess(ph,ProcessBasicInformation,@pbi,SizeOf(pbi),@dwread)) then begin
    OutputDebugString(Pchar('Failed Get PEB Location : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {Reading PEB}
  if not NtSuccess(ZwReadVirtualMemory(ph,pbi.PebBaseAddress,@PEB,sizeof(PEB),@dwread)) then begin
    OutputDebugString(Pchar('Failed Reading PEB : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {Reading LoaderData}
  if not NtSuccess(ZwReadVirtualMemory(ph,PEB.Ldr,@LdrData,sizeof(LdrData),@dwread)) then begin
    OutputDebugString(Pchar('Failed Reading LdrData : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {init for enum the linked list}
  i := 0;
  Head := 0;
  Current := DWord(LdrData.InLoadOrderModuleList.Flink);

  { loop for all ldr entry or module }
  repeat

    {Reading Current entry}
    if not NtSuccess(ZwReadVirtualMemory(ph,Ptr(Current),@LdrModule,sizeof(LdrModule),@dwread)) then begin
      OutputDebugString(Pchar('Failed Reading Current Module : '+SysErrorMessage(Getlasterror)));
      break;
    end;

    {Check if this our target}
    if (DWord(LdrModule.DllBase) = mh) then begin

      { Get NewModule Name Length}
      LdrModule.FullDllName.Length := lstrlenW(NewModulename) * 2;

      { Allocate Buffer to target process }
      pNewAddr := nil;
      if not NtSuccess(ZwAllocateVirtualMemory(ph, @pNewAddr, 0, @LdrModule.FullDllName.Length, MEM_COMMIT, PAGE_READWRITE)) then begin
        OutputDebugString(Pchar('Failed Alloc Memory : '+SysErrorMessage(Getlasterror)));
        exit;
     end;

     { Write Our NewModulename to target process}
     if not NtSuccess(ZwWriteVirtualMemory(ph, pNewAddr, NewModulename, LdrModule.FullDllName.Length, nil)) then begin
        OutputDebugString(Pchar('Failed Write Our NewModulename : '+SysErrorMessage(Getlasterror)));
        exit;
     end;

     { set buffer to new address}
     LdrModule.FullDllName.Buffer := pNewAddr;
     OutputDebugString(LdrModule.FullDllName.Buffer);

     { write our LdrModule}
     if not NtSuccess(ZwWriteVirtualMemory(ph, Ptr(Current), @LdrModule, sizeof(LdrModule), nil)) then begin
        OutputDebugString(Pchar('Failed Write Our LdrModule : '+SysErrorMessage(Getlasterror)));
        exit;
     end;

      break;
    end;

    {Next Module}
    if i=0 then Head := Dword(LdrModule.InLoadOrderLinks.Blink);
    Current := Dword(LdrModule.InLoadOrderLinks.Flink);
    inc(i);
  until Current = Head;
end;

Procedure Unlink(ph : THandle; Link : TListEntry32);
var
  Blink, Flink  : DWord;
begin
  Blink := Dword(Link.Blink);
  Flink := Dword(Link.Flink);

  { write our flink in module blink}
  ZwWriteVirtualMemory(ph, Ptr(Blink+DWord(@TListEntry32(nil^).Flink)), @Flink, sizeof(Flink), nil);

  { write our blink in module flink}
  ZwWriteVirtualMemory(ph, Ptr(Flink+DWord(@TListEntry32(nil^).Blink)), @Blink, sizeof(Blink), nil);
end;

Procedure UnlinkModule(ph,mh : THandle);
var
  pbi           : PROCESS_BASIC_INFORMATION;
  PEB           : TPeb32;
  LdrData       : TPebLdrData32;
  LdrModule     : TLdrDataTableEntry32;
  i, dwread     : DWord;
  Head,Current  : DWord;
begin

  {Get PROCESS_BASIC_INFORMATION}
  if not NtSuccess(ZwQueryInformationProcess(ph,ProcessBasicInformation,@pbi,SizeOf(pbi),@dwread)) then begin
    OutputDebugString(Pchar('Failed Get PEB Location : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {Reading PEB}
  if not NtSuccess(ZwReadVirtualMemory(ph,pbi.PebBaseAddress,@PEB,sizeof(PEB),@dwread)) then begin
    OutputDebugString(Pchar('Failed Reading PEB : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {Reading LoaderData}
  if not NtSuccess(ZwReadVirtualMemory(ph,PEB.Ldr,@LdrData,sizeof(LdrData),@dwread)) then begin
    OutputDebugString(Pchar('Failed Reading LdrData : '+SysErrorMessage(Getlasterror)));
    exit;
  end;

  {init for enum the linked list}
  i := 0;
  Head := 0;
  Current := DWord(LdrData.InLoadOrderModuleList.Flink);

  { loop for all ldr entry or module }
  repeat

    {Reading Current entry}
    if not NtSuccess(ZwReadVirtualMemory(ph,Ptr(Current),@LdrModule,sizeof(LdrModule),@dwread)) then begin
      OutputDebugString(Pchar('Failed Reading Current Module : '+SysErrorMessage(Getlasterror)));
      break;
    end;

    {Check if this our target}
    if (DWord(LdrModule.DllBase) = mh) then begin

      { Unlink The linked list }
      Unlink(ph,LdrModule.InLoadOrderLinks);
      Unlink(ph,LdrModule.InMemoryOrderLinks);
      Unlink(ph,LdrModule.InInitializationOrderLinks);
      Unlink(ph,LdrModule.u1.HashLinks);

      break;
    end;

    {Next Module}
    if i=0 then Head := Dword(LdrModule.InLoadOrderLinks.Blink);
    Current := Dword(LdrModule.InLoadOrderLinks.Flink);
    inc(i);
  until Current = Head;
end;

end.


and example use
Kode: [Pilih]
var
h : THandle;
begin
  EnumPeb(thandle(-1));
  h := RemoteModuleHandle(thandle(-1),'Project1.exe');
  RemoteModuleImageName(thandle(-1),h);
  RemotePatchModuleFileName(thandle(-1),h,pchar(paramstr(0)+'asadasdsa'));
  messagebox(0,pchar(paramstr(0)),nil,mb_ok);
  UnlinkModule(thandle(-1),h);
  EnumPeb(thandle(-1));
end.

btw u need this unit by Nico Bendlin
http://www.bendlins.de/nico/delphi/NcxWOW64.zip

linkinmyblog
http://cybercoding.wordpress.com/2011/04/18/delphi-peb-module-manipulation/

originalthread
http://virusindonesia.com/forum/viewtopic.php?id=840