-2

I have some websites that have been attacked and infected with malware.

There are 800+ files that need to be updated and the string is exactly the same in each file.

What I want to do is find all the files that have the malware, and then delete the offending string from the file.

I have found some command line scripts which work fine when tested on a basic string:

perl -pi -w -e 's/string_to_find//g;' test-file.php

and when combined into the find command:

find . -type f | xargs grep 'string_to_find' -sl | xargs perl -pi -w -e 's/string_to_find//g;'

Now my problem is getting that to work on the string which is an extremely long and and complex string:

<?php @error_reporting(0); if (!isset($eva1fYlbakBcVSir)) {$eva1fYlbakBcVSir = "random_string_7365_characters_long";$eva1tYlbakBcVSir = "string_of_encoded_characters";$eva1tYldakBcVSir = "string_of_encoded_characters";$eva1tYldakBoVS1r = "string_of_encoded_characters";$eva1tYidokBoVSjr = "string_of_encoded_characters";$eva1tYldokBcVSjr=$eva1tYldakBcVSir($eva1tYldakBoVS1r);$eva1tYldakBcVSjr=$eva1tYldakBcVSir($eva1tYlbakBcVSir);$eva1tYidakBcVSjr = $eva1tYldakBcVSjr(chr(2687.5*0.016), $eva1fYlbakBcVSir);$eva1tYXdakAcVSjr = $eva1tYidakBcVSjr[0.031*0.061];$eva1tYidokBcVSjr = $eva1tYldakBcVSjr(chr(3625*0.016), $eva1tYidokBoVSjr);$eva1tYldokBcVSjr($eva1tYidokBcVSjr[0.016*(7812.5*0.016)],$eva1tYidokBcVSjr[62.5*0.016],$eva1tYldakBcVSir($eva1tYidokBcVSjr[0.061*0.031]));$eva1tYldakBcVSir = "";$eva1tYldakBoVS1r = $eva1tYlbakBcVSir.$eva1tYlbakBcVSir;$eva1tYidokBoVSjr = $eva1tYlbakBcVSir;$eva1tYldakBcVSir = "string_of_encoded_characters";$eva1tYlbakBcVSir = "string_of_encoded_characters";$eva1tYldakBoVS1r = "string_of_encoded_characters";$eva1tYldakBcVSir = "";$eva1tYldakBoVS1r = $eva1tYlbakBcVSir.$eva1tYlbakBcVSir;$eva1tYidokBoVSjr = $eva1tYlbakBcVSir;} ?>

Now, when I try the search and replace with the full string (escaping all the special characters) I get this result:

Possible unintended interpolation of @error_reporting in string at -e line 1.
Name "main::error_reporting" used only once: possible typo at -e line 1.

Is it possible to do what I am trying to do or is the string impossible to capture? Do I need to escape the @ symbol differently? (I escaped with a \ and that didn't work)

Any help - I am a novice with bash and perl

php-b-grader
  • 3,191
  • 11
  • 42
  • 53

4 Answers4

1

The \@ ought to work, but you've got other problems too: <? matches an optional <, for example, not the sequence <?. According to man perlre, the following ought to work:

perl -pi -w -e 's/\Q<?php \E@\Qerror_reporting...//g'

The \Q turns off all special regexp meanings, allowing you to search for an exact string without quoting every metacharacter. The \E restores the special meaning temporarily, but since @ is isolated it is not interpreted as the beginning of an array name. You'll have to surround each @ and $ the same way. And then of course, do check that this works properly! Good luck.

Edit: In truth I would recommend replacing your one-liner with a simple script. Define the string you want to search for, ensuring that no unwanted variable substitution occurs (print it out to make sure); disable all special characters with quotemeta() to disable their regular-expression meaning; and apply to the input. That's if the string is really EXACTLY the same; if the "random_string..." differs from place to place, you need to build your RE more carefully. In any case, it'll make your life easier if you write a 5-line perl script, get it to work on one file, and then use the find/xargs method to apply it everywhere.

alexis
  • 48,685
  • 16
  • 101
  • 161
0

You probably want to back out to the command-line and use sed. It's built for precisely this type of problem. Here is a good place to get started: IBM Developerworks SED by example

uotonyh
  • 786
  • 5
  • 7
0

Regular expressions have other features that could make this task easier. If you don't have any valid code with variables that start with $evalfYl, then you can use a much simpler regular expression with less to escape:

perl -pi -w -e \
's/<\?php \@error_reporting\(0\);if \(!isset(\$evalYl.*?} \?>//g' \
 test-file.php

where .*? will match any characters up to the next occurrence of "} ?>" in the string.

mob
  • 117,087
  • 18
  • 149
  • 283
  • Ok, but it wouldn't matter anyway if I did because it would need to be preceded by @error_reporting(0)... anyway wouldn't it? Also, you have escaped the @ so I do need to escape this in perl? – php-b-grader Mar 28 '12 at 01:12
0

I figured it out. The statement was correct, I had just missed escaping some characters.

So in answer to my question, the answer is:

Yes - the method used is correct and works in achieving the desired result Yes - The @ symbol must also be escaped

Escape the string correctly and the statement works fine.

php-b-grader
  • 3,191
  • 11
  • 42
  • 53