放个源码(PE资源表提取所有图标)
delphi吧
全部回复
仅看楼主
level 1
热情的LSET 楼主
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
OpenDialog1: TOpenDialog;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
DOS_Header:PImageDosHeader;//映像文件基地址
nt_header:PImageNtHeaders;
idx:integer;
filename:string;
implementation
uses PE;
{$R *.dfm}
procedure PickIcon(va:PIMAGE_RESOURCE_DIRECTORY;st:cardinal);//va资源类型的指针 st资源表在文件中的位置
var
ImageResourceDirectoryEntry:PIMAGE_RESOURCE_DIRECTORY_ENTRY;
ImageResourceDirectory:PIMAGE_RESOURCE_DIRECTORY;
ImageResourceDataEntry:PIMAGE_RESOURCE_DATA_ENTRY;
v:PIMAGE_RESOURCE_DIRECTORY;
NumberOfName,NumberOfId:word;
i,j:byte;
fs1:TFileStream;
offs:cardinal;
// buf:array[0..1023] of byte;
buf:pointer;
r:cardinal;
PEIconDirEntry:PPEIconDirEntry;
IconDirEntry:PIconDirEntry;
IconDir:PIconDir;
IconDirBuf:PIconDir;
begin
new(IconDirBuf);
new(IconDir);
new(IconDirEntry);
new(PEIconDirEntry);
NumberOfName:=va.NumberOfNamedEntries;
NumberOfId:=va.NumberOfIdEntries;
ImageResourceDirectoryEntry:=PIMAGE_RESOURCE_DIRECTORY_ENTRY(cardinal(va)+SizeOf(_IMAGE_RESOURCE_DIRECTORY));
// IconDirBuf.idreserved:=0;
// IconDirBuf.idtype:=1;
// IconDirBuf.idcount:=1;
for i:=0 to NumberOfName+NumberOfId-1 do
begin
// if (Hiword(ImageResourceDirectoryEntry.Name)=0) and (ImageResourceDirectoryEntry.Name=14) then//最高位为0表是以ID命名,且Name为图标组ID=14
if (Hiword(ImageResourceDirectoryEntry.Name)=0) then//最高位为0表是以ID命名
begin
if ((ImageResourceDirectoryEntry.OffsetToData and $80000000) =0) then
begin
//资源数据块指针
ImageResourceDataEntry:=PIMAGE_RESOURCE_DATA_ENTRY(st+(ImageResourceDirectoryEntry.OffsetToData and $7FFFFFFF));
fs1:=TFileStream.Create('e:\'+filename+IntToStr(Idx)+'.ico',fmOpenWrite);
offs:=cardinal(DOS_Header) + RVAToOffset(ImageResourceDataEntry.OffsetToData,nt_header);//数据块在文件中的绝对位置
buf:=AllocMem(ImageResourceDataEntry.Size);
ReadProcessMemory(GetCurrentProcess,pointer(offs), buf,ImageResourceDataEntry.Size,r);//读取文件中的数据
fs1.Position:=fs1.Size;
fs1.Write(buf^,ImageResourceDataEntry.Size);
fs1.Free;
inc(idx);
//FreeMemory(buf);
end else
begin
//下一级目录块
v:=PIMAGE_RESOURCE_DIRECTORY(st+(ImageResourceDirectoryEntry.OffsetToData and $7FFFFFFF));
PickIcon(v,st);
end;
end;
inc(ImageResourceDirectoryEntry);
end;
end;
procedure PickGroupIcon(va:PIMAGE_RESOURCE_DIRECTORY;st:cardinal);//va资源类型的指针 st资源表在文件中的位置
var
ImageResourceDirectoryEntry:PIMAGE_RESOURCE_DIRECTORY_ENTRY;
ImageResourceDirectory:PIMAGE_RESOURCE_DIRECTORY;
ImageResourceDataEntry:PIMAGE_RESOURCE_DATA_ENTRY;
v:PIMAGE_RESOURCE_DIRECTORY;
NumberOfName,NumberOfId:word;
i,j:byte;
fs:TFileStream;
offs:cardinal;
buf:array [0..127] of byte;
r:cardinal;
PEIconDirEntry:PPEIconDirEntry;
IconDirEntry:PIconDirEntry;
IconDir:PIconDir;
IconDirBuf:PIconDir;
begin
new(IconDirBuf);
new(IconDir);
new(IconDirEntry);
new(PEIconDirEntry);
NumberOfName:=va.NumberOfNamedEntries;
NumberOfId:=va.NumberOfIdEntries;
ImageResourceDirectoryEntry:=PIMAGE_RESOURCE_DIRECTORY_ENTRY(cardinal(va)+SizeOf(_IMAGE_RESOURCE_DIRECTORY));
IconDirBuf.idreserved:=0;
IconDirBuf.idtype:=1;
IconDirBuf.idcount:=1;
for i:=0 to NumberOfName+NumberOfId-1 do
begin
// if (Hiword(ImageResourceDirectoryEntry.Name)=0) and (ImageResourceDirectoryEntry.Name=14) then//最高位为0表是以ID命名,且Name为图标组ID=14
if (Hiword(ImageResourceDirectoryEntry.Name)=0) then//最高位为0表是以ID命名
begin
if ((ImageResourceDirectoryEntry.OffsetToData and $80000000) =0) then
begin
//资源数据块指针
ImageResourceDataEntry:=PIMAGE_RESOURCE_DATA_ENTRY(st+(ImageResourceDirectoryEntry.OffsetToData and $7FFFFFFF));
// fs:=TFileStream.Create('e:\'+IntToStr(idx)+'.ico',fmCreate);
offs:=cardinal(DOS_Header) + RVAToOffset(ImageResourceDataEntry.OffsetToData,nt_header);//数据块在文件中的绝对位置
IconDir:=PIconDir(offs);
//ReadProcessMemory(GetCurrentProcess,pointer(offs),@buf,sizeof(ICON_DIR),r);
showmessage(inttostr( IconDir.idcount));
PEIconDirEntry:=PPEIconDirEntry(cardinal(offs)+sizeof(ICON_DIR));
//IconDir:=@buf;
for j:=0 to IconDir.idcount-1 do
begin
fs:=TFileStream.Create('e:\'+filename+IntToStr(PEIconDirEntry.dwImageOffset)+'.ico',fmCreate);
IconDirEntry^.bWidth:=PEIconDirEntry^.bWidth;
IconDirEntry^.bHeight:=PEIconDirEntry^.bHeight;
IconDirEntry^.bColorCount:=PEIconDirEntry^.bColorCount;
IconDirEntry^.bReserved:=PEIconDirEntry^.bReserved;
IconDirEntry^.wPlanes:=PEIconDirEntry^.wPlanes;
IconDirEntry^.wBitCount:=PEIconDirEntry^.wBitCount;
IconDirEntry^.dwBytesInRes:=PEIconDirEntry^.dwBytesInRes;
IconDirEntry^.dwImageOffset:=$16;
// ReadProcessMemory(GetCurrentProcess,pointer(offs), @buf,ImageResourceDataEntry.Size,r);//读取文件中的数据
fs.Write(IconDirBuf^,sizeof(ICON_DIR));
fs.Write(IconDirEntry^,sizeof(ICON_DIR_ENTRY));
fs.Free;
//inc(idx);
inc(PEIconDirEntry);
end;
// ReadProcessMemory(GetCurrentProcess,pointer(offs), @buf,ImageResourceDataEntry.Size,r);//读取文件中的数据
// fs.Write(buf,ImageResourceDataEntry.Size);
// fs.Free;
// inc(idx);
end else
begin
//下一级目录块
v:=PIMAGE_RESOURCE_DIRECTORY(st+(ImageResourceDirectoryEntry.OffsetToData and $7FFFFFFF));
PickGroupIcon(v,st);
end;
end;
inc(ImageResourceDirectoryEntry);
end;
//dispose(IconDirBuf);
//dispose(IconDir);
//dispose(IconDirEntry);
//dispose(PEIconDirEntry);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
st:cardinal;//资源表在文件中的起始位置
ImageResourceDirectory:PIMAGE_RESOURCE_DIRECTORY;
ImageResourceDirectoryEntry:PIMAGE_RESOURCE_DIRECTORY_ENTRY;
ImageResourceDataEntry:PIMAGE_RESOURCE_DATA_ENTRY;
offset:cardinal;//资源表在文件中的偏移
NumberOfName,NumberOfId:word;
i:byte;
begin
OpenDialog1.Execute;
filename:=ExtractFileName(OpenDialog1.FileName);
DOS_Header:=PImageDosHeader(GetStartAddress(PAnsiChar(OpenDialog1.FileName)));//映像文件基地址
nt_header:=PImageNtHeaders( DOS_Header._lfanew + cardinal(DOS_Header) );//NT头
offset:=RVAToOffset(nt_header.OptionalHeader.DataDirectory[2].VirtualAddress, nt_header); //资源表在文件中的偏移
st:=offset+cardinal(DOS_Header);//资源表在文件中的起始位置
ImageResourceDirectory:=PIMAGE_RESOURCE_DIRECTORY( offset+cardinal(DOS_Header) );//第一层目录
NumberOfName:=ImageResourceDirectory.NumberOfNamedEntries;
NumberOfId:=ImageResourceDirectory.NumberOfIdEntries;
ImageResourceDirectoryEntry:=PIMAGE_RESOURCE_DIRECTORY_ENTRY(cardinal(ImageResourceDirectory)+SizeOf(_IMAGE_RESOURCE_DIRECTORY));
for i:=0 to NumberOfName+NumberOfId-1 do
begin
if (Hiword(ImageResourceDirectoryEntry.Name)=0) and (ImageResourceDirectoryEntry.Name=14) then//最高位为0,且Name为图标组
begin
ImageResourceDirectory:=PIMAGE_RESOURCE_DIRECTORY(st+(ImageResourceDirectoryEntry.OffsetToData and $7FFFFFFF));
break;
end;
inc(ImageResourceDirectoryEntry);
end;
PickGroupIcon(ImageResourceDirectory,st);
//idx:=1;
//sleep(1000);
ImageResourceDirectory:=PIMAGE_RESOURCE_DIRECTORY( offset+cardinal(DOS_Header) );//第一层目录
NumberOfName:=ImageResourceDirectory.NumberOfNamedEntries;
NumberOfId:=ImageResourceDirectory.NumberOfIdEntries;
ImageResourceDirectoryEntry:=PIMAGE_RESOURCE_DIRECTORY_ENTRY(cardinal(ImageResourceDirectory)+SizeOf(_IMAGE_RESOURCE_DIRECTORY));
for i:=0 to NumberOfName+NumberOfId-1 do
begin
if (Hiword(ImageResourceDirectoryEntry.Name)=0) and (ImageResourceDirectoryEntry.Name=3) then//最高位为0,且Name为图标
begin
ImageResourceDirectory:=PIMAGE_RESOURCE_DIRECTORY(st+(ImageResourceDirectoryEntry.OffsetToData and $7FFFFFFF));
break;
end;
inc(ImageResourceDirectoryEntry);
end;
PickIcon(ImageResourceDirectory,st);
idx:=1;
{
NumberOfName:=ImageResourceDirectory.NumberOfNamedEntries;
NumberOfId:=ImageResourceDirectory.NumberOfIdEntries;
ImageResourceDirectoryEntry:=ImageResourceDirectory+SizeOf(_IMAGE_RESOURCE_DIRECTORY);
for i:=0 to NumberOfName+NumberOfId-1 do
begin
if (Hiword(ImageResourceDirectoryEntry.Name)=0) and (ImageResourceDirectoryEntry.Name=RT_GROUP_ICON) then//最高位为0,且Name为图标组
begin
if (ImageResourceDirectoryEntry.OffsetToData and $80000000) =0 then
begin
//资源数据块指针
ImageResourceDataEntry:=PIMAGE_RESOURCE_DATA_ENTRY(st+(ImageResourceDirectoryEntry.OffsetToData and $7FFFFFFF));
end else
begin
//下一级目录块
ImageResourceDirectory:=PIMAGE_RESOURCE_DIRECTORY(st+(ImageResourceDirectoryEntry.OffsetToData and $7FFFFFFF));
end;
end;
inc(ImageResourceDirectoryEntry);
end;
}
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
idx:=1;
end;
end.
2014年04月28日 13点04分 1
level 1
热情的LSET 楼主
unit PE;
interface
uses
Windows, Dialogs, SysUtils,Unit1;
type
PIconDir=^TIconDir;
ICON_DIR = packed record
idreserved:word;//保留字,必须为0
idtype:word;//资源类别,1表示为ICO文件
idcount: word;//图标数量
end;
TIconDir=ICON_DIR;
type //ICO文件中的ICO文件头结构
PIconDirEntry=^TIconDirEntry;
ICON_DIR_ENTRY=packed record
bWidth:byte; //宽度
bHeight:byte; //高度
bColorCount:byte; //颜色数
bReserved:byte; //保留字,为0
wPlanes:word; //调色板
wBitCount:word; //每个像素的位数
dwBytesInRes:dword; //资源长度
dwImageOffset:dword; //资源在文件偏移
end;
TIconDirEntry=ICON_DIR_ENTRY;
type //pe文件中的ICO结构头
PPEIconDirEntry=^TPEIconDirEntry;
PE_ICON_DIR_ENTRY=packed record
bWidth:byte; //宽度
bHeight:byte; //高度
bColorCount:byte; //颜色数
bReserved:byte; //保留字,为0
wPlanes:word; //调色板
wBitCount:word; //每个像素的位数
dwBytesInRes:dword; //资源长度
dwImageOffset:word; //资源在文件偏移
end;
TPEIconDirEntry=PE_ICON_DIR_ENTRY;
type
PIMAGE_RESOURCE_DATA_ENTRY = ^TImageResourceDataEntry;
_IMAGE_RESOURCE_DATA_ENTRY = packed record
OffsetToData:DWORD;
Size:DWORD;
CodePage:DWORD;
Reserved:DWORD;
end;
TImageResourceDataEntry = _IMAGE_RESOURCE_DATA_ENTRY;
type
PIMAGE_RESOURCE_DIRECTORY_ENTRY = ^TImageResourceDirectoryEntry;
_IMAGE_RESOURCE_DIRECTORY_ENTRY = packed record
Name:DWORD;
OffsetToData:DWORD;
end;
TImageResourceDirectoryEntry = _IMAGE_RESOURCE_DIRECTORY_ENTRY;
type
PIMAGE_RESOURCE_DIRECTORY = ^TImageResourceDirectory;
_IMAGE_RESOURCE_DIRECTORY = packed record
Characteristics:DWORD;
TimeDateStamp:DWORD;
MajorVersion:WORD;
MinorVersion:WORD;
NumberOfNamedEntries:WORD;
NumberOfIdEntries:WORD;
end;
TImageResourceDirectory = _IMAGE_RESOURCE_DIRECTORY;
type
PImageImportByName = ^TImageImportByName;
_IMAGE_IMPORT_BY_NAME=packed record
hint:word;
name1:Byte;
end;
TImageImportByName=_IMAGE_IMPORT_BY_NAME;
type
PImageImprotDescriptor = ^TImageImprotDescriptor;
_IMAGE_IMPORT_DESCRIPTOR= packed record
OriginalFirstThunk:dword;
TimeDateStamp:DWORD;
ForwarderChain:dword;
Name:dword;
FirstThunk:dword;
end;
TImageImprotDescriptor= _IMAGE_IMPORT_DESCRIPTOR;
//-------------------------------------------------------
//取得映射后的基地址
function GetStartAddress(exe_path:PAnsiChar):pointer;
//-------------------------------------------------------
//-------------------------------------------------------
//寻找RVA在哪个节,并将内存偏移量RVA转换为文件偏移量
function RVAToOffset(rva:cardinal ; nt_header:PImageNtHeaders):integer;
//-------------------------------------------------------
//-------------------------------------------------------
//遍历PE文件的导入表DLL名
//procedure GetImportDLL(base:cardinal; nt_header:PImageNtHeaders);
//-------------------------------------------------------
//-------------------------------------------------------
//遍历PE文件的导入表函数名
//procedure GetImportFun(base:cardinal; nt_header:PImageNtHeaders; DLLName:string);
//-------------------------------------------------------
implementation
2014年04月28日 13点04分 2
level 1
热情的LSET 楼主
function GetStartAddress(exe_path:PAnsiChar):pointer;
var
hmpping:pointer;
hand,hand1:cardinal;
begin
hand:=CreateFile(exe_path,
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0); //取得文件句柄
if hand=INVALID_HANDLE_VALUE then ShowMessage('取文件句柄失败');
hand1:=CreateFileMapping(hand,nil,PAGE_READWRITE,0,0,nil);//创建文件映射
if hand1=0 then ShowMessage('创建文件映射对象失败');
hmpping:=MapViewOfFile(hand1,FILE_MAP_ALL_ACCESS,0,0,0);//映射到当前应用程序的地址空间
if hmpping=nil then ShowMessage('映射到当前应用程序的地址空间失败');
result:=hmpping;
end;
{
procedure GetImportDLL(base:cardinal; nt_header:PImageNtHeaders);
var
offset:cardinal;
ImageImportDescriptor:PImageImprotDescriptor;
buf:array[0..MAX_PATH] of char;
r:cardinal;
begin
offset:=RVAToOffset(nt_header.OptionalHeader.DataDirectory[1].VirtualAddress, nt_header); //输入表在文件中的偏移
ImageImportDescriptor:=PImageImprotDescriptor(base+offset);//输入表在文件中的绝对地址
Repeat
offset:=RVAToOffset(ImageImportDescriptor.Name, nt_header);//DLL名字在文件中的偏移
ReadProcessMemory(GetCurrentProcess, pointer(base+offset), @buf, length(buf),r);//读取文件中的数据
Form1.ListBox1.Items.Add(string(buf));
inc(ImageImportDescriptor);
Until ImageImportDescriptor.Name=0;//判断DLL名字的RVA是否为0
end;
}
{
procedure GetImportFun(base:cardinal; nt_header:PImageNtHeaders; DLLName:string);
var
offset:cardinal;
ImageImportDescriptor:PImageImprotDescriptor;
ImageImportByName:PImageImportByName;
ImageThunkData:pdword;
buf:array[0..MAX_PATH] of char;
dd:dword;
Namebuf:byte;
r:cardinal;
begin
offset:=RVAToOffset(nt_header.OptionalHeader.DataDirectory[1].VirtualAddress, nt_header); //输入表在文件中的偏移
ImageImportDescriptor:=PImageImprotDescriptor(base+offset);//输入表在文件中的绝对地址
Repeat
offset:=RVAToOffset(ImageImportDescriptor.Name, nt_header);//DLL名字在文件中的偏移
ReadProcessMemory(GetCurrentProcess, pointer(base+offset), @buf, length(buf),r);//读取文件中的数据
if string(buf)=DLLName then
begin
if ImageImportDescriptor.OriginalFirstThunk = 0 then//某些单桥结构这个数为0,例如DELPHI程序
begin
offset:=RVAToOffset(ImageImportDescriptor.FirstThunk, nt_header);//Image_Thunk_Data结构在文件中的偏移
end else
begin
offset:=RVAToOffset(ImageImportDescriptor.OriginalFirstThunk, nt_header);
end;
ImageThunkData:=pdword(base+offset);//Image_Thunk_Data结构在文件中的绝对地址
repeat
if ImageThunkData^ or $7FFFFFFF = $7FFFFFFF then //Image_Thunk_Data的值如果最高位是0表示这个值是指向Image_Import_By_Name结构的一个RVA
begin
offset:=RVAToOffset(ImageThunkData^, nt_header);//Image_Import_By_Name结构在文件中的偏移
ImageImportByName:=PImageImportByName(base+offset);//Image_Import_By_Name结构在文件中的绝对地址
ReadProcessMemory(GetCurrentProcess,@ImageImportByName.name1, @buf, length(buf),r);
form1.ListBox2.Items.Add(String(buf));
end else
begin
form1.ListBox2.Items.Add(format('序号:%xH',[loword(ImageThunkData^)]));//Image_Thunk_Data的值如果最高位是1表示这个值是序号
end;
inc(ImageThunkData);
until ImageThunkData^ = 0;
break;
end;
inc(ImageImportDescriptor);
Until ImageImportDescriptor.Name=0;//判断DLL名字的RVA是否为0
end;
}
function RVAToOffset(rva:cardinal ; nt_header:PImageNtHeaders):integer;
var
section:PImageSectionHeader;
off,i:integer;
begin
section:=PImageSectionHeader(integer(nt_header)+SizeOf(IMAGE_NT_HEADERS));
for i:=1 to nt_header.FileHeader.NumberOfSections do
begin
if (rva >=section.VirtualAddress) and (rva < section.VirtualAddress+section.SizeOfRawData) then
begin
off:=rva-section.VirtualAddress;
result:=section.PointerToRawData+off;
exit;
end;
inc(section);
end;
end;
end.
2014年04月28日 13点04分 3
level 1
热情的LSET 楼主
写了很多天了!!!,最主要还是要理解PE资源表
2014年04月28日 13点04分 4
level 10
建议提供网盘下载。不然代码很乱。
2014年04月29日 03点04分 5
1