📄 exeimage.pas
字号:
wValue,wCharLen: WORD;
begin
tmpStrList := TStringList.Create;
tmpFixedFileInfoList := TStringList.Create;
try
//
with tmpFixedFileInfoList do
begin
Add('CompanyName');
Add('FileDescription');
Add('FileVersion');
Add('InternalName');
Add('LegalCopyright');
Add('LegalTrademarks');
Add('OriginalFilename');
Add('ProductName');
Add('ProductVersion');
Add('Comments');
Add('PrivateBuild');
Add('SpecialBuild');
end;
//
AOffset := AOffset + SizeOf(TVSVersionInfoHeader);
FExeStream.Seek(AOffset,0);
FExeStream.Read(tmpStringFileInfoHeader,SizeOf(tmpStringFileInfoHeader));
if tmpStringFileInfoHeader.szKey='StringFileInfo' then
begin
FExeStream.Read(tmpStringTableHeader,SizeOf(tmpStringTableHeader));
tmpStringInfoLen := SizeOf(tmpStringTableHeader);
//本部分更改了,因为发现tmpStringValueHeader.wLength保存的长度不一定正确
//所以改用其wType=01来判断,原来的代码片段查看2003-1-28日的.
while tmpStringInfoLen < tmpStringTableHeader.wLength do
begin
//主要去掉'\0',其实可能超过了tmpStringVAlueHeader.wLength,所以放弃用tmpStringVAlueHeader.
repeat
FExeStream.Read(wValue,SizeOf(wValue));
tmpStringInfoLen := tmpStringInfoLen + SizeOf(wValue);
until wValue<>0;
//刚才那个是长度,需要再跳两个
wCharLen := wValue div SizeOf(wValue) - 3;
FExeStream.Read(wValue,SizeOf(wValue)); //相当于wValueLength
FExeStream.Read(wValue,SizeOf(wValue)); //相当于wType
tmpStringInfoLen := tmpStringInfoLen + 2* SizeOf(wValue);
tmpStr := '';
for wValue:=0 to wCharLen-1 do
begin
FExeStream.Read(tmpWChar,SizeOf(tmpWChar));
tmpStringInfoLen := tmpStringInfoLen + SizeOf(tmpWChar);
tmpStr := tmpStr + tmpWChar;
end;
tmpStr := trim(tmpStr);
if tmpStr <>'' then
begin
if Pos(#0,tmpStr)=0 then
begin
tmpComp := tmpStr;
tmpStr := '';
end
else begin
tmpComp := Copy(tmpStr,0,Pos(#0,tmpStr)-1);
tmpStr := Copy(tmpStr,Length(tmpComp)+1,Length(tmpStr));
tmpStr := trim(tmpStr);
end;
if tmpFixedFileInfoList.IndexOf(tmpComp)<>-1 then
begin
tmpStrList.Add(tmpComp);
tmpStrList.Add(tmpStr);
end;
end;
end;
end;
finally
tmpFixedFileInfoList.Free;
end;
result := tmpStrList;
end;
{ 取得版本信息 - 文件其它信息 }
function TExeImage.GetVSVerFileInfo(AOffset:Integer):TStringList;
var
tmpStrList : TStringList;
tmpStringFileInfoHeader: TStringFileInfoHeader;
tmpVerFileInfoHeader:TVerFileInfoHeader;
tmpVerSimpleHeader: TVerSimpleHeader;
tmpVerFileInfoHeaderLen,tmpVerSimpleHeaderLen: Integer;
tmpStr:String;
tmpWChar: WChar;
tmpWd: WORD;
begin
tmpStrList := TStringList.Create;
// -> TStringFileInfo
AOffset := AOffset + SizeOf(TVSVersionInfoHeader);
FExeStream.Seek(AOffset,0);
FExeStream.Read(tmpStringFileInfoHeader,SizeOf(tmpStringFileInfoHeader));
// -> TVerFileInfo
AOffset := AOffset + tmpStringFileInfoHeader.wLength; //重新定位.
FExeStream.Seek(AOffset,0);
FExeStream.Read(tmpVerFileInfoHeader,SizeOf(tmpVerFileInfoHeader));
tmpVerFileInfoHeaderLen := SizeOf(tmpVerFileInfoHeader);
while tmpVerFileInfoHeaderLen < tmpVerFileInfoHeader.wLength do
begin
FExeStream.Read(tmpVerSimpleHeader,SizeOf(tmpVerSimpleHeader));
tmpVerSimpleHeaderLen := SizeOf(tmpVerSimpleHeader);
tmpVerFileInfoHeaderLen := tmpVerFileInfoHeaderLen + SizeOf(tmpVerSimpleHeader);
//取"\0"结尾的字符串
tmpStr:='';
repeat
FExeStream.Read(tmpWChar,SizeOf(tmpWChar));
tmpVerSimpleHeaderLen := tmpVerSimpleHeaderLen+SizeOf(WChar);
tmpVerFileInfoHeaderLen :=tmpVerFileInfoHeaderLen+SizeOf(WChar);
tmpStr := tmpStr + tmpWChar;
until tmpWChar=Chr(0);
tmpStrList.Add(trim(tmpStr));
//一个padding
FExeStream.Read(tmpWd,SizeOf(tmpWd));
tmpVerSimpleHeaderLen := tmpVerSimpleHeaderLen+SizeOf(tmpWd);
tmpVerFileInfoHeaderLen :=tmpVerFileInfoHeaderLen+SizeOf(tmpWd);
tmpStr:='';
//之后的
while tmpVerSimpleHeaderLen < tmpVerSimpleHeader.wLength do
begin
FExeStream.Read(tmpWd,SizeOf(tmpWd));
tmpVerSimpleHeaderLen := tmpVerSimpleHeaderLen+SizeOf(tmpWd);
tmpVerFileInfoHeaderLen :=tmpVerFileInfoHeaderLen+SizeOf(tmpWd);
tmpStr:=tmpStr+Format('%.4x',[tmpWd]);
end;
tmpStrList.Add(tmpStr);
end;
result:=tmpStrList;
end;
{ 取得版本信息中的软件语言特性 }
function TExeImage.GetVSLanguageID(AOffset,ASize:Integer):DWORD;
var
tmpWd1,tmpWd2: WORD;
begin
//直接取最后两个Word; 这个办法不太行.
FExeStream.Seek(AOffset+ASize-2*SizeOf(tmpWd1),0);
FExeStream.Read(tmpWd1,SizeOf(tmpWd1));
FExeStream.Read(tmpWd2,SizeOf(tmpWd2));
result := MakeLong(tmpWd2,tmpWd1);
{
方法二
var
tmpStringFileInfoHeader: TStringFileInfoHeader;
tmpVerFileInfoHeader:TVerFileInfoHeader;
tmpVerSimpleHeader: TVerSimpleHeader;
tmpVerFileInfoHeaderLen,tmpVerSimpleHeaderLen: Integer;
tmpStr:String;
tmpWChar: WChar;
tmpWd1,tmpWd2: WORD;
tmpdWd: DWORD;
begin
tmpdWd := $FFFFFFFF;
// -> TStringFileInfo
AOffset := AOffset + SizeOf(TVSVersionInfoHeader);
FExeStream.Seek(AOffset,0);
FExeStream.Read(tmpStringFileInfoHeader,SizeOf(tmpStringFileInfoHeader));
// -> TVerFileInfo
AOffset := AOffset + tmpStringFileInfoHeader.wLength; //重新定位.
FExeStream.Seek(AOffset,0);
FExeStream.Read(tmpVerFileInfoHeader,SizeOf(tmpVerFileInfoHeader));
tmpVerFileInfoHeaderLen := SizeOf(tmpVerFileInfoHeader);
while tmpVerFileInfoHeaderLen < tmpVerFileInfoHeader.wLength do
begin
FExeStream.Read(tmpVerSimpleHeader,SizeOf(tmpVerSimpleHeader));
tmpVerSimpleHeaderLen := SizeOf(tmpVerSimpleHeader);
tmpVerFileInfoHeaderLen := tmpVerFileInfoHeaderLen + SizeOf(tmpVerSimpleHeader);
//取"\0"结尾的字符串
tmpStr:='';
repeat
FExeStream.Read(tmpWChar,SizeOf(tmpWChar));
tmpVerSimpleHeaderLen := tmpVerSimpleHeaderLen+SizeOf(WChar);
tmpVerFileInfoHeaderLen :=tmpVerFileInfoHeaderLen+SizeOf(WChar);
tmpStr := tmpStr + tmpWChar;
until tmpWChar=Chr(0); //这部分会有问题
if trim(tmpStr) = 'Translation' then
begin
FExeStream.Read(tmpWd1,SizeOf(tmpWd1));//为的是跳一个Word
FExeStream.Read(tmpWd1,SizeOf(tmpWd1));
FExeStream.Read(tmpWd2,SizeOf(tmpWd2));
tmpdWd := MakeLong(tmpWd2,tmpWd1);
break;
end;
tmpVerFileInfoHeaderLen:=tmpVerFileInfoHeaderLen+(tmpVerSimpleHeader.wLength-tmpVerSimpleHeaderLen);
end;
result := tmpdWd;
}
end;
function TExeImage.ExportDirAddr: Integer;
var
i,CurIndex:integer;
tmpCurRVA,tmpSectionRVA: DWORD;
begin
tmpCurRVA := FPENTHead.OptionalHeader.DataDirectory[0].VirtualAddress;
tmpSectionRVA := 0;
CurIndex := -1;
for i:=0 to FSectionNum-1 do
if (FPESectionHead[i].VirtualAddress>tmpSectionRVA)and(FPESectionHead[i].VirtualAddress<=tmpCurRVA) then
begin
tmpSectionRVA := FPESectionHead[i].VirtualAddress;
CurIndex := i;
end;
result := FPESectionHead[CurIndex].PointerToRawData + (tmpCurRVA-tmpSectionRVA);
end;
function TExeImage.ExportDirSize: Integer;
begin
result := FPENTHead.OptionalHeader.DataDirectory[0].Size;
end;
function TExeImage.ImportDirAddr: Integer;
var
i,CurIndex:integer;
tmpCurRVA,tmpSectionRVA: DWORD;
begin
//由RVA找出文件偏移位置.
//如果导入为 $7FA0, 然而有节表为 $7000,$9000,则此导入区在节表$7000,
//而对于$7000,实际指向的位置为$5C00,则$7FA0实际指向为 $7FA0-$7000+$5C00=$6BA0
tmpCurRVA := FPENTHead.OptionalHeader.DataDirectory[1].VirtualAddress;
tmpSectionRVA := 0;
CurIndex := -1;
//求出最接近当前tmpDirRVA的块表,(最小于等于tmpDirRVA)
for i:=0 to FSectionNum-1 do
if (FPESectionHead[i].VirtualAddress>tmpSectionRVA)and(FPESectionHead[i].VirtualAddress<=tmpCurRVA) then
begin
tmpSectionRVA := FPESectionHead[i].VirtualAddress;
CurIndex := i;
end;
result := FPESectionHead[CurIndex].PointerToRawData + (tmpCurRVA-tmpSectionRVA);
end;
function TExeImage.ImportDirSize: Integer;
begin
result := FPENTHead.OptionalHeader.DataDirectory[1].Size;
end;
{ 导出的名称 }
function TExeImage.ExportName: String;
var
tmpExportDir:TExportDirectory;
tmpName: Char;
tmpStr: String;
tmpOffset: DWORD;
begin
with FExeStream do
begin
tmpOffset := FPENTHead.OptionalHeader.DataDirectory[0].VirtualAddress - ExportDirAddr;
Seek(ExportDirAddr,0);
Read(tmpExportDir,SizeOf(tmpExportDir));
//将RVA转换成文件偏移值
Seek(tmpExportDir.Name - tmpOffset,0);
tmpStr :='';
repeat
Read(tmpName,SizeOf(tmpName));
tmpStr := tmpStr + tmpName;
until tmpName=Chr(0);
end;
result := trim(tmpStr);
end;
{ 导入的名称列表 }
function TExeImage.GetImportName:TStringList;
var
tmpStrList:TStringList;
tmpImportDesc: TIMAGE_IMPORT_DESCRIPTOR;
tmpRealAddr,tmpOffset: Integer;
CurPosition: DWORD;
tmpChar:Char;
tmpStr: String;
begin
tmpStrList := TStringList.Create;
CurPosition := ImportDirAddr;
tmpOffset := FPENTHead.OptionalHeader.DataDirectory[1].VirtualAddress - CurPosition;
FExeStream.Seek(CurPosition,0);
FExestream.Read(tmpImportDesc,SizeOf(tmpImportDesc));
CurPosition := CurPosition + SizeOf(tmpImportDesc);
while tmpImportDesc.Name<>0 do
begin
tmpRealAddr := tmpImportDesc.Name - tmpOffset;
tmpStr := '';
FExeStream.Seek(tmpRealAddr,0);
repeat
FExeStream.Read(tmpChar,SizeOf(tmpChar));
tmpStr := tmpStr + tmpChar;
until tmpChar=Chr(0);
tmpStr := trim(tmpStr);
tmpStrList.Add(tmpStr);
FExeStream.Seek(CurPosition,0);
FExeStream.Read(tmpImportDesc,SizeOf(tmpImportDesc));
CurPosition := CurPosition + SizeOf(tmpImportDesc);
end;
result := tmpStrList;
end;
{ 导入的函数列表 }
function TExeImage.GetImportFunction(AIndexOfName:WORD):TStringList;
var
tmpStrList:TStringList;
tmpImportDesc: TIMAGE_IMPORT_DESCRIPTOR;
tmpRealAddr,tmpOffset: DWORD;
CurPosition: DWORD;
tmpChar:Char;
tmpStr: String;
FuncNameAddr:DWORD;
FuncID: WORD;
begin
tmpStrList := TStringList.Create;
CurPosition := ImportDirAddr;
tmpOffset := FPENTHead.OptionalHeader.DataDirectory[1].VirtualAddress - CurPosition;
CurPosition := CurPosition + AIndexOfName*SizeOf(tmpImportDesc);
FExeStream.Seek(Curposition,0);
FExeStream.Read(tmpImportDesc,SizeOf(tmpImportDesc));
//读取函数名称的地址.
CurPosition := tmpImportDesc.FirstThunk-tmpOffset;
FExeStream.Seek(CurPosition,0);
FExeStream.Read(FuncNameAddr,SizeOf(FuncNameAddr));
CurPosition := CurPosition + SizeOf(FuncNameAddr);
while FuncNameAddr<>0 do
begin
tmpRealAddr := FuncNameAddr - tmpOffset;
if tmpRealAddr <= FExeStream.Size then
begin
FExeStream.Seek(tmpRealAddr,0);
FExeStream.Read(FuncID,SizeOf(FuncID));
tmpStr := '';
repeat
FExeStream.Read(tmpChar,SizeOf(tmpChar));
tmpStr := tmpStr + tmpChar;
until tmpChar=Chr(0);
tmpStr := trim(tmpStr);
if tmpStr='' then tmpStr := '()';
end
else begin
//在处理空的函数时FuncID不正确.好像没有读到.
FuncID := tmpRealAddr and $7FFFFFFF;
tmpStr := '()';
end;
tmpStrList.Add(Format('%.4x,%s',[FuncID,tmpStr]));
FExeStream.Seek(CurPosition,0);
FExeStream.Read(FuncNameAddr,SizeOf(FuncNameAddr));
CurPosition := CurPosition + SizeOf(FuncNameAddr);
end;
result := tmpStrList;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -