Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Virus protection for Perl scripts

by tachyon (Chancellor)
on Jun 28, 2001 at 10:00 UTC ( #92225=perlmeditation: print w/replies, xml ) Need Help??

Having perhaps made an error of judgement at Morality of posting Perl "virus" code? after discovering a new Perl toy to play with I now feel the need to atone. Here is a short piece of code that you could add to a script to prevent it from running if it has been modified by *say* a virus but in all liklihood you!

This begin block could be placed anywhere in a script and appends a simple checksum to the end of that script the first time it is executed. On following executions it checks against this checksum for a change and aborts if a change is noted. A simple edit will remove the checksum from the end of the file reseting this protection. The length of the file is used as the checksum for speed but you could get as elaborate as you liked.

This script is not a virus but does change any file it is run within. The appended checksum is removed prior to execution so will cause no problems.



#!/usr/bin/perl -w print "Hello World!\n"; BEGIN { local $/; open (ME,$0); my $me = <ME>; close ME; unless ($me =~ m/#avshc='\d+'$/) { my $length = length $me; open (ME, ">>$0"); print ME "#avshc='$length'"; close ME; $me .= "#avshc='$length'"; } $me =~ s/#avshc='(\d+)'$//; die "File $0 has changed ?viral infection?\n" unless $1 == length +$me; }

Replies are listed 'Best First'.
Re (tilly) 1: Virus protection for Perl scripts
by tilly (Archbishop) on Jun 28, 2001 at 12:05 UTC
    If someone feels up to it, the right way to do this is to write a module that will take each file it is used in and checks a PGP signature against a list of known valid PGP signatures. It would skip any file with a known MD5 signature. The list of MD5 signatures would, of course, correspond to the existing installed modules and the list of PGP signatures would correspond to the public keys of authorized developers. Both lists would be installed by root and therefore could not easily be modified by users. (You need two lists because you might run into trouble if you alter existing installed modules. PGP allows people to sign modules. MD5 avoids having to change the module.)

    It is easy to use this module liberally. What should be doable is modifying perl to insert the check for every single file that is loaded.

    This anti-virus protection would take some work, would be a pain in the rear end, and would slow Perl. But you could at long last sleep at night confident that your Perl code was not being modified without the knowledge and consent of an authorized person. Unless the PGP keys got compromised, but then you can rescind keys.

    BTW anyone heading down the path of cryptographically signed Perl code should look at some of the other possible uses for cryptography. If your imagination fails, look at ACME::Bleach and friends...

      A use Virus::Protect; strategy would easily be circumvented by:

      BEGIN { local $/; open ME,"+<$0"; $_ = <ME>; s/#use\s+Virus::Protect\s*;\s*\n//; s/BEGIN {.+?Virus::Protect.+?\n}//s; seek ME,0,0; truncate ME,0; print ME $_; close ME; eval $_; exit; } #use Virus::Protect; print "Hello World!\n";

      If a postulated virus inserted this BEGIN block it would erase the postulated use Virus::Protect line and the BEGIN block. That is why I did not wrap the sample code in a module. It needs to be modified (polymorphic) to be effective - see comments below. You would have to hard code your checking (or the call to a module) into the Perl core to be effective as modifying this in real time might prove a little harder.

      I don't quite know how ACME::Bleach relates but you might like to look at :-)



        I am aware of that. Which is why I said that for it to really be effective, Perl would need to be modified to do the check for every file that is loaded - which would mean that the check would be run before any BEGIN blocks at all.

        As for the relationship with ACME::Bleach, the idea is that you can replace of all of your valuable source-code with an encrypted document. This could be decrypted by the correct module and a public key. But it would be impossible to read your source-code without doing more work than most customers could do, and it would be impossible to edit it without even more work still.

        Yeah, useless against knowledgable programmers. But still you could impress the PHB...

        Of course, if the Virus::Protect module changes the syntax (see ACME::Bleach or Lingua::Romana::Perliata?) good look with strip off.
Re: Virus protection for Perl scripts
by Abigail (Deacon) on Jun 28, 2001 at 17:44 UTC
    Actually, that isn't going to work against all attacks. In fact, it doesn't even work against the code I posted yesterday in the thread about virusses. That is because my virus installs itself in a BEGIN block right below the first line (it assumes the first line is the she-bang line). Hence, it gets executed (and does its damage) before your check aborts the program. (And yeah, putting the BEGIN all the way at the top was done by design) The only thing you gained is that you get alarmed as soon as damage is done - but then it's too late already.

    -- Abigail

      You are correct that this post is misnamed in using the word 'Protection' - it should have been 'Warning'. There is little you can currently do to prevent a perl script running with sufficient permissions to write to files writing to files! You can detect this though, which was the point.

      Detecting damage is a worthwhile endeavour as you can run a script like:

      #!/usr/bin/perl -w # # this code will remove the viral infection when run in same dir # as a virus if you add the viral code to the data section local $/; $signature = <DATA>; 1 while $signature =~ s/\n$//g; $signature = quotemeta $signature; while (<*>) { next unless $_ =~ m/\.(pl|cgi|pm)$/; open (FILE, "<$_") or die "Unable to check $_ for infection"; $check_if_infected = <FILE>; close FILE; if ($check_if_infected =~ s/^$signature//) { open (CLEAN, ">$_") or die "Unable to disinfect $_"; print CLEAN $check_if_infected; close CLEAN; print "Uninfected $_\n"; } } __DATA__ # Viral code goes here as the viral signature

      Whist neither of these pieces of code 'prevent' infection by either your code, mine or any of the others, if you add these two pieces of code together you can detect and repair which is about the best you can hope for without writing some very OS invasive antiviral software. Noton Antivirus slows my dos box by a measured 50-60% for most tasks as it is continually vetting executing threads.

Re: Virus protection for Perl scripts
by $code or die (Deacon) on Jun 28, 2001 at 17:15 UTC
    I wonder if it would be difficult for a perl virus to change the line:
    die "File $0 has changed ?viral infection?\n" unless $1 == length $me;
    #die "File $0 has changed ?viral infection?\n" unless $1 == length $me +;
    update: or even to run this regex on the script: s/#avshc='\d+'//g;

    $ perldoc perldoc

      No a virus could be easily written to defeat this particular code. This presumes that you install this *exact* code. However you can easily change the checkstring to *whatever*, and/or the message thus defeating a virus using a regex to disable this type of code. Polymorphic protection if you want. Using file length could be defeated by a virus that deleted the same number of bytes as it adds but this significantly ups the difficulty factor as the virus needs to delete some 'code' without breaking the target file.

      The problem with any *standard* modular solution would be that s/use Virus::Protect;// (just like s/#avshc='\d+'//g; etc) would be far too easy to implement in a virus so you would need to hard code antiviral protection into the Perl core and run it automatically. There are a large number of difficulties with this solution revolving on how Perl is supposed to differentiate between a valid request to change a file from by a script and a virally initiated one?



        I might be mis-understanding what you're saying. I think you're saying that while I could write a virus to break that particular virus protection, it wouldn't necessarily work if the syntax was different?

        I think you have that the wrong way round: there will always be ways to break any anti-virus code you try and impliment. If you're writing a virus, you'd find ways around the anti-virus software. This is the nature of regular viruses. It's the anti-virus software companies that need to keep up with the viruses, not the other way around.

        I'm no virus expert, but there are ways of infecting someone's code without setting off this kind of warning.

        Not all viruses are benign "worms". Some viruses do much worse things than that.

        <self-edited because I don't want to give anyone ideas>

        You said:
        Using file length could be defeated by a virus that deleted the same number of bytes as it adds but this significantly ups the difficulty factor as the virus needs to delete some 'code' without breaking the target file.
        Why would someone writing a virus to infect your code necessarily care if it breaks your code?

        Personally, I like the idea you propose in your second paragraph tye mentioned earlier. It's not perfect, but here's how I might impliment it:

        1. Write a module, let's call it Virus::Protect, or maybe something less obvious.
        2. the module should do some kind of check - timestamp or md5hash or PGP signed or only allow certain named scripts to be run
        3. Don't show anyone this code.
        4. rename your perl binary to say /vperl(\.exe)?/i
        5. write a shell or batch script called "perl(\.bat)?" which runs the command: vperl -MVirus::Protect %1
        6. Now all your perl scripts will run with the Virus::Protect module and unless you look closely, people might not find out.
        Note, I haven't tried this, and of course there will still be ways of hurting my system. But it's a bit more transparent (or less opaque!).

        Of course a better solution, would be to unplug your modem\dsl\network cable, rip out your cdrom and floppy drives, and don't let anyone near your machine. But then life would be a bit boring!

        Forgive me if I misunderstood. I'm not attacking you, this is a useful discussion. It's just the thought of open-source virus protection software is a bit strange to me, but I'd love to be proven wrong!

        $ perldoc perldoc

        Update: some minor reformatting to empasise the real points I'm trying to convey, and attributed the virus::protect to tye, since he mentioned something similar in the first reply.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://92225]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2020-11-26 12:56 GMT
Find Nodes?
    Voting Booth?

    No recent polls found