http://www.perlmonks.org?node_id=1020559

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have the following code which is working, but it not exactly what I need:
#!/usr/bin/perl use File::Copy; use strict; # Set to list of files with malware present # This is produced by the following command line # grep -Rl eva1fYlbakBcVSir /var/www/html/ > /var/scripts/problem_file +s.txt # or # grep -Rl 7kyJ7kSKioDTWVWeRB3TiciL1UjcmRiLn4SKiAETs90cuZlTz5mROtHWHd +/var/www/html/ > /var/scripts/problem_files.txt my $file_list = "/var/scripts/problem_files.txt"; # Set test to 1 for test run (nothing changed, only files are listed). # Set test to 0 to actually clean the files my $test=0; #Next line works WITHOUT the php script ending at the beginning of the + malware line my $text1 = "\<\?php\ \@error_reporting\(0\)\;\ if\ \(\!isset\(\$eva1f +YlbakBcVSir\)\)\ \{\$eva1fYlbakBcVSir\ \=\ \"7kyJ"; #Next line works WITH php script ending at the beginning of the malwar +e line my $text2 = "\?\>\<\?php\ \@error_reporting\(0\)\;\ if\ \(\!isset\(\$e +va1fYlbakBcVSir\)\)\ \{\$eva1fYlbakBcVSir\ \=\ \"7kyJ"; #Next line works WITH ending </html> at the beginning of the malware l +ine my $text3 = "\<\/html\>\<\?php\ \@error_reporting\(0\)\;\ if\ \(\!isse +t\(\$eva1fYlbakBcVSir\)\)\ \{\$eva1fYlbakBcVSir\ \=\ \"7kyJ"; #Next line works WITH ending </div> at the beginning of the malware li +ne my $text4 = "\<\/div\>\<\?php\ \@error_reporting\(0\)\;\ if\ \(\!isset +\(\$eva1fYlbakBcVSir\)\)\ \{\$eva1fYlbakBcVSir\ \=\ \"7kyJ"; open (FILELIST, $file_list) or die "can't open $file_list: $!"; foreach my $file (<FILELIST>) { my $temp_file; print "Now cleaning $file\n" if (!$test); chomp $file; # get rid of line ending return open (FILE, $file) or die "can't open $file: $!"; foreach my $line (<FILE>) { if ($line =~ /^\Q$text1\E/) { print "file: $file\n" if ($test); print "malware line (test1): $line\n\n" if ($test); $line = ""; }elsif ($line =~ /^\Q$text2\E/) { print "file: $file\n" if ($test); print "malware line (test2): $line\n\n" if ($test); $line = "?>"; }elsif ($line =~ /^\Q$text3\E/) { print "file: $file\n" if ($test); print "malware line (test3): $line\n\n" if ($test); $line = "</html>"; }elsif ($line =~ /^\Q$text4\E/) { print "file: $file\n" if ($test); print "malware line (test4): $line\n\n" if ($test); $line = "</div>"; } if (!$test) { my $backup_file="$file" . "_INFECTED_COPY"; #copy("$file","$backup_file") or die "Copy failed: $!"; $temp_file="$file" . "_INFECTED_TEMP"; open (TEMPFILE,">>", $temp_file) or die "can't open $temp_ +file for writing: $!"; print TEMPFILE $line; }# end if not test }# end foreach $file close (FILE); close (TEMPFILE); rename("$temp_file", "$file") || die ( "Error renaming INFECTED_TE +MP file" ) if (!$test); }# end sub each file close (FILELIST);
As you can see, I am using the grep command to locate files that have a certain string of characters in them. Then, I am opening that list of files within this script and searching for the specific string that I wish to remove. However, I have found that the string something exists on a line starting with other text. At first, I thought I could run through each option within an if/else but I am finding too many options.

So what I need, (sudo code) is something like a regex that says (ignore what the lines starts with but replace any text that is between \<\?php\ \@error_reporting\(0\)\;\ if\ \(\!isset\(\$eva1fYlbakBcVSir\)\)\ \{\$eva1fYlbakBcVSir\ \=\ \"7kyJ
and more exact text to be defined until it gets to abc123 which is the end of the text to be replaced. Then leave anything that comes after that as well. I could probably handle this on my own if it were not for the fact that I am having to quote everything to get it to work. That has made it extremely difficult for me. Any help would be appreciated.

Thank you.