首页
社区
课程
招聘
[求助]请教,PE文件的资源替换问题。
发表于: 2008-8-16 13:51 7611

[求助]请教,PE文件的资源替换问题。

2008-8-16 13:51
7611
 我想直接替换PE文件资源中的图标文件,前面已经实现对图标的地址定位了,就是替换方面有点难题

var
FResourceBase ,sourceBase:PImageResourceDirectory ;
te,entry:PImageResourceDirectoryEntry;
iconEntry:PImageResourceDirectoryEntry;
tempDir:PImageResourceDirectory;
tempEntry:PImageResourceDirectoryEntry;
firstIconDir:PImageResourceDirectory;
firstIconEntry:PImageResourceDirectoryEntry;
firstIconData: PImageResourceDataEntry;
pFirstIcon:word;
SEChea:PImageSectionHeader;
fhandle:LongWord;
DOS:PImageDosHeader;
 nts:PImageNtHeaders;
 buffer:pchar;
 size,i,j,K:integer;
ofn:openfilename;
hMapping:thandle;
map:pointer;

//去掉最高位
function StripHighBit(L: Longint): DWORD;
begin
  Result := L and IMAGE_OFFSET_STRIP_HIGH;
end;

begin

getmem(buffer,256);
 int:=false;
ofn.lStructSize:=sizeof(openfilename);
ofn.nMaxFile:=512;
ofn.lpstrFile:=buffer;
ofn.lpstrFilter:='*.exe';
ofn.Flags:=OFN_FILEMUSTEXIST or OFN_HIDEREADONLY or OFN_EXPLORER;
GetOpenFileNameA(ofn);
CopyFile(buffer,'New.exe',false);
fhandle:=createfile(buffer,GENERIC_READ, FILE_SHARE_READ,nil,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0);
hMapping:=CreateFileMapping(fhandle,NiL,PAGE_READONLY,0,0,0);
map:=mapviewoffile(hmapping,FILE_MAP_READ,0,0,0);
dos:=map;
if dos^.e_magic<>IMAGE_DOS_SIGNATURE then
messagebox(0,'错误的PE文件格式!','OK',0);
cardinal(nts):=cardinal(dos)+dos^._lfanew;
if nts^.Signature<>IMAGE_NT_SIGNATURE then
messagebox(0,'错误的PE文件格式!1','OK',0);

SEChea := PImageSectionHeader(NTS);
Inc(PImageNtHeaders(SEChea));
 for I := 0 to NTS^.FileHeader.NumberOfSections - 1 do
  begin

    if Strlicomp(@SEChea^.Name, PChar('.rsrc'), IMAGE_SIZEOF_SHORT_NAME) = 0 then
    begin
 FResourceBase := PImageResourceDirectory(SEChea^.PointerToRawData + LongWord(Dos));
messagebox(0,pchar('OK FOUND FILES IS '+IntToHex(LongWord(@FResourceBase),8)),'OK',0);
   break;
    end;
    Inc(SEChea);
    continue;
  end;
sourceBase:=PImageResourceDirectory(SEChea^.PointerToRawData + LongWord(Dos));
Entry:=PImageResourceDirectoryEntry(longWORD(sourceBase)+sizeof(TImageResourceDirectory));
te:=entry;

for J := 1 to FResourceBase^.NumberOfIdEntries+FResourceBase^.NumberOfNamedEntries  do
 BEGIN
if te^.Name = 3  THEN
 BEGIN
iconEntry:=PIMAGERESOURCEDIRECTORYENTRY(LongWord(FResourceBase)+StripHighBit(te^.OffsetToData));//找到 Icon 的资源目录了!!!
BREAK;
  end;
  inc(te);
  CONTINUE;
END;
tempDir:=PIMAGERESOURCEDIRECTORY(iconEntry);
tempEntry:=PIMAGERESOURCEDIRECTORYENTRY(LongWord(tempDir)+sizeof(TIMAGERESOURCEDIRECTORY));

for K := 0 to tempDir^.NumberOfIdEntries+tempDir^.NumberOfNamedEntries - 1 do
begin
if (StripHighBit(tempEntry.OffsetToData) >0) and(k=0)  THEN
BEGIN
firstIconDir:=PIMAGERESOURCEDIRECTORY(LongWord(FResourceBase)+StripHighBit(tempEntry.OffsetToData));
firstIconEntry:=PIMAGERESOURCEDIRECTORYENTRY(LongWord(firstIconDir)+sizeof(TIMAGERESOURCEDIRECTORY));
firstIconData:= PIMAGERESOURCEDATAENTRY(LongWord(FResourceBase)+StripHighBit(firstIconEntry.OffsetToData));
end;
inc(entry);
END;
pFirstIcon:= firstIconData.OffsetToData - sechea.VirtualAddress + LongWord(FResourceBase);
writeln('file address : '+inttohex(pFirstIcon,8));
writeln('file rva address : '+inttohex(firstIconData.OffsetToData,8));
writeln('file size  : '+inttohex(firstIconData.Size,8));

// 下面是替换图标代码,哪位仁兄可以完成之?

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
替换可执行文件的图标还是资源中的所有图标?
如果只需要替换PE的图标的话,不用这么麻烦的
几个API就可以搞定
2008-8-16 13:57
0
雪    币: 224
活跃值: (58)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我想替换资源中指定的图标,仁兄是否有很好的见解呢?
2008-8-16 14:00
0
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
4
不好意思,没有
上面我说那个还是在某本杂志上看到的
2008-8-16 14:56
0
雪    币: 224
活跃值: (58)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
呵呵,没什么的
2008-8-16 15:34
0
雪    币: 224
活跃值: (58)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
哪位仁兄可以帮帮我饿?
2008-8-16 17:54
0
雪    币: 219
活跃值: (58)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
DEMO
UpdateIcons('c:\test.exe','C:\xx.ico');

procedure UpdateIcons(const FileName, IcoFileName: String);

implementation

function EnumLangsFunc(hModule: Cardinal; lpType, lpName: PAnsiChar; wLanguage: Word; lParam: Integer): BOOL; stdcall;
begin
  PWord(lParam)^ := wLanguage;
  Result := False;
end;

function GetResourceLanguage(hModule: Cardinal; lpType, lpName: PAnsiChar; var wLanguage: Word): Boolean;
begin
  wLanguage := 0;
  EnumResourceLanguages(hModule, lpType, lpName, @EnumLangsFunc, Integer(@wLanguage));
  Result := True;
end;

procedure UpdateIcons(const FileName, IcoFileName: String);
type
  PIcoItemHeader = ^TIcoItemHeader;
  TIcoItemHeader = packed record
    Width: Byte;
    Height: Byte;
    Colors: Byte;
    Reserved: Byte;
    Planes: Word;
    BitCount: Word;
    ImageSize: DWORD;
  end;
  PIcoItem = ^TIcoItem;
  TIcoItem = packed record
    Header: TIcoItemHeader;
    Offset: DWORD;
  end;
  PIcoHeader = ^TIcoHeader;
  TIcoHeader = packed record
    Reserved: Word;
    Typ: Word;
    ItemCount: Word;
    Items: array [0..MaxInt shr 4 - 1] of TIcoItem;
  end;
  PGroupIconDirItem = ^TGroupIconDirItem;
  TGroupIconDirItem = packed record
    Header: TIcoItemHeader;
    Id: Word;
  end;
  PGroupIconDir = ^TGroupIconDir;
  TGroupIconDir = packed record
    Reserved: Word;
    Typ: Word;
    ItemCount: Word;
    Items: array [0..MaxInt shr 4 - 1] of TGroupIconDirItem;
  end;

  function IsValidIcon(P: Pointer; Size: Cardinal): Boolean;
  var
    ItemCount: Cardinal;
  begin
    Result := False;
    if Size < Cardinal(SizeOf(Word) * 3) then
      Exit;
    if (PChar(P)[0] = 'M') and (PChar(P)[1] = 'Z') then
      Exit;
    ItemCount := PIcoHeader(P).ItemCount;
    if Size < Cardinal((SizeOf(Word) * 3) + (ItemCount * SizeOf(TIcoItem))) then
      Exit;
    P := @PIcoHeader(P).Items;
    while ItemCount > Cardinal(0) do begin
      if (Cardinal(PIcoItem(P).Offset + PIcoItem(P).Header.ImageSize) < Cardinal(PIcoItem(P).Offset)) or
         (Cardinal(PIcoItem(P).Offset + PIcoItem(P).Header.ImageSize) > Cardinal(Size)) then
        Exit;
      Inc(PIcoItem(P));
      Dec(ItemCount);
    end;
    Result := True;
  end;

var
  H: THandle;
  M: HMODULE;
  R: HRSRC;
  Res: HGLOBAL;
  GroupIconDir, NewGroupIconDir: PGroupIconDir;
  I: Integer;
  wLanguage: Word;
  F: TFile;
  Ico: PIcoHeader;
  N: Cardinal;
  NewGroupIconDirSize: LongInt;
begin
  if Win32Platform <> VER_PLATFORM_WIN32_NT then
    Error('仅支持 Windows NT 和后期版本');

  Ico := nil;

  try
    { Load the icons }
    F := TFile.Create(IcoFileName, fdOpenExisting, faRead, fsRead);
    try
      N := F.CappedSize;
      if Cardinal(N) > Cardinal($100000) then  { sanity check }
        Error('图标文件太大');
      GetMem(Ico, N);
      F.ReadBuffer(Ico^, N);
    finally
      F.Free;
    end;

    { Ensure the icon is valid }
    if not IsValidIcon(Ico, N) then
      Error('图标文件无效');

    { Update the resources }
    H := BeginUpdateResource(PChar(FileName), False);
    if H = 0 then
      ErrorWithLastError('BeginUpdateResource 无效 (1)');
    try
      M := LoadLibraryEx(PChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
      if M = 0 then
        ErrorWithLastError('LoadLibraryEx 无效 (1)');
      try
              { Load the 'MAINICON' group icon resource }
        R := FindResource(M, 'MAINICON', RT_GROUP_ICON);
        if R = 0 then
          ErrorWithLastError('FindResource 无效 (1)');
        Res := LoadResource(M, R);
        if Res = 0 then
          ErrorWithLastError('LoadResource 无效 (1)');
        GroupIconDir := LockResource(Res);
        if GroupIconDir = nil then
          ErrorWithLastError('LockResource 无效 (1)');

        { Delete 'MAINICON' }
        if not GetResourceLanguage(M, RT_GROUP_ICON, 'MAINICON', wLanguage) then
          Error('GetResourceLanguage 无效 (1)');
        if not UpdateResource(H, RT_GROUP_ICON, 'MAINICON', wLanguage, nil, 0) then
          ErrorWithLastError('UpdateResource 无效 (1)');

        { Delete the RT_ICON icon resources that belonged to 'MAINICON' }
        for I := 0 to GroupIconDir.ItemCount-1 do begin
          if not GetResourceLanguage(M, RT_ICON, MakeIntResource(GroupIconDir.Items[I].Id), wLanguage) then
            Error('GetResourceLanguage 无效 (2)');
          if not UpdateResource(H, RT_ICON, MakeIntResource(GroupIconDir.Items[I].Id), wLanguage, nil, 0) then
            ErrorWithLastError('UpdateResource 无效 (2)');
        end;

        { Build the new group icon resource }
        NewGroupIconDirSize := 3*SizeOf(Word)+Ico.ItemCount*SizeOf(TGroupIconDirItem);
        GetMem(NewGroupIconDir, NewGroupIconDirSize);
        try
          { Build the new group icon resource }
          NewGroupIconDir.Reserved := GroupIconDir.Reserved;
          NewGroupIconDir.Typ := GroupIconDir.Typ;
          NewGroupIconDir.ItemCount := Ico.ItemCount;
          for I := 0 to NewGroupIconDir.ItemCount-1 do begin
            NewGroupIconDir.Items[I].Header := Ico.Items[I].Header;
            NewGroupIconDir.Items[I].Id := I+1; //assumes that there aren't any icons left
          end;

          { Update 'MAINICON' }
          for I := 0 to NewGroupIconDir.ItemCount-1 do
            if not UpdateResource(H, RT_ICON, MakeIntResource(NewGroupIconDir.Items[I].Id), 2052, Pointer(DWORD(Ico) + Ico.Items[I].Offset), Ico.Items[I].Header.ImageSize) then
              ErrorWithLastError('UpdateResource 无效 (3)');

          { Update the icons }
          if not UpdateResource(H, RT_GROUP_ICON, 'MAINICON', 2052, NewGroupIconDir, NewGroupIconDirSize) then
            ErrorWithLastError('UpdateResource 无效 (4)');
        finally
          FreeMem(NewGroupIconDir);
        end;
      finally
        FreeLibrary(M);
      end;
    except
      EndUpdateResource(H, True);  { discard changes }
      raise;
    end;
    if not EndUpdateResource(H, False) then
      ErrorWithLastError('EndUpdateResource 无效');
  finally
    FreeMem(Ico);
  end;
end;
2008-8-16 17:57
0
雪    币: 212
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
是在黑防上看的吧,好像名字叫做骑着蜗牛去散步发表的。
2008-8-17 21:17
0
游客
登录 | 注册 方可回帖
返回
//