While this article uses the term "virus", the code demonstrated here is not a virus or any other form of malware. If you use this program to annoy your co-workers - you may have to deal with the repercussions!
Who said programming cannot be fun? Let's create a simple "memory eater" that executes itself an unlimited number of times - thus consuming all the Windows memory :)
The "Hello World VIRUS" we will build in this article is, of course, not a true virus. We'll create a totally useless application that executes itself when it gets executed. What a weird idea :)
Here are the topics you will learn by building your first (Hello World) Virus:
- Execute applications from Code,
- Send Parameters to applications being executed from code,
- Use Windows CallBack procedures,
- Get the Class Name and the Caption of a Window if you know its Handle,
- Send and Handle a Custom Message
"Hello World" VIRUS!In the OnCreate event of the main (only form) form a ShellExecute method is called to execute another application from code - this time, the calling application - itself. When you run the virus for the first time, the Virus will execute itself and another instance will be created. The second instance, again, executes itself by creating the third instance, the third instance runs the fourth instance ... get the point?
Ok, ok. Let's build a fair virus. The Virus will execute itself only a limited number of times. The last instance will clean up the system by terminating all the running instances.
The MAXExecuteCount constant determines the maximum number of times the virus will execute itself. Another instance is started using the ShellExecute method - by passing the EXE name of the Virus itself and the current instance count. When the virus is run, the ParamCount is used to check if any parameters are passed to the program (execCount variable holds this number). If it is less then MAXExecuteCount the Virus executes itself again. A random number is used to position the window erratically on the screen (download full source).
procedure THelloWorldVirusForm.FormCreate(Sender: TObject) ; //How many times to execute this application - "virus"? const MAXExecuteCount = 55; var execCount : integer; begin execCount := 0; if ParamCount > 0 then execCount := StrToInt(ParamStr(1)) ; if execCount < MAXExecuteCount then begin infoLabel.Caption := Format('Clone Nr: %d',[execCount]) ; //run itself again execCount := 1 + execCount; ShellExecute(Application.Handle,'open',PChar(Application.ExeName),PChar(IntToStr(execCount)),'',SW_SHOW) ; end else begin //Let's be fair .. kill all clones... Application.MessageBox('Hello, Scared?',PChar(Application.Title)) ; Caption := 'I will close normally'; KillClones; Application.MessageBox('System secured!',PChar(Application.Title)) ; end; end;
When MAXExecuteCount is reached, since this is not a bad virus, the last instance ensures that all the running instances are terminated.
The KillClones function uses a Windows callback mechanism to enumerate all top-level windows and search for the Hello World Virus instances:
The EnumWindows fills a TStringList with the handles of the running Virus instances. A simple for loop is used to send a custom message to the Virus instance.
procedure THelloWorldVirusForm.KillClones; var cloneHandle : THandle; cloneHandles : TStringList; sHandle : string; begin cloneHandles := TStringList.Create; try EnumWindows(@EnumWindowsFunc, LParam(cloneHandles)) ; for sHandle in cloneHandles do begin cloneHandle := StrToInt(sHandle) ; if cloneHandle <> self.Handle then SendMessage(cloneHandle, WM_CloneQuit, 0, 0) ; end; finally cloneHandles.Free; end; end;
The Virus handles the custom message by calling Application.Terminate.
function EnumWindowsFunc(Handle: THandle; List: TStringList) : boolean ; stdcall; var className: array[0..255] of Char; caption: array[0..255] of Char; begin GetClassName(Handle, className, SizeOf(className)-1) ; GetWindowText(Handle, caption, SizeOf(caption)-1) ; if ((className = 'THelloWorldVirusForm') AND (caption = 'HelloWorldVirusForm')) then List.Add(IntToStr(Handle)) ; Result :=True; end;
const WM_CloneQuit = WM_USer + 2901; //"random" number ... procedure Quit(var Msg : TMessage) ; message WM_CloneQuit; ... procedureTHelloWorldVirusForm.Quit(var Msg: TMessage) ; begin Application.Terminate; end;
Final WARNING: do NOT execute the Hello World Virus from the Delphi IDE, build the code and start the program from the Windows Explorer. If you run the application from the IDE - one instace will be left running. Use the Task Manager to terminate it.