如何使用 sed 命令替换第二次出现之前的所有内容?

如何使用 sed 命令替换第二次出现之前的所有内容?

我的网站感染了一些不良恶意软件,这些恶意软件已在至少 3135 个文件(我的所有 WordPress 网站)上插入了恶意代码。

这是受感染的文件之一:http://pastebin.com/FXU1ht4R

这是我想要的输出:http://pastebin.com/YPJwjiWH

find除了一些简单的和grep命令之外,我对 Unix 命令一无所知。

经过一番研究后,我发现了该sed命令,但我不知道如何在我的情况下使用它。

从上面的代码可以看出,一般模式是代码插入到每个文件的顶部,即在原始标签之前<?php(这意味着现在原始<?php标签是第二个)。

cnajwp =所以我想我可以找到包含第二个标签之前的所有文件并删除所有内容<?php

cnajwp我可以通过使用找到包含的文件

find * -type f -name "*.php" -exec grep -l "cnajwp =" {} \;

但我不知道如何替换<?php这些事件的第二个标签之前的所有内容。

这里有人可以帮我吗?

答案1

这将使用您的命令来查找受感染的文件,并将列表提供给 xargs,后者在第一行运行一个表达式。

find * -type f -name "*.php" -exec grep -l "cnajwp =" {} \; |
xargs sed -i -E '1s/^(<\?php) \$ocnajwp =.*$/\1/'

根据您的输入文件示例,这应该可以解决问题。

由于与此同时您发现了文件,其中感染的位置略有不同,并且您最终得到了一些文件,其中第一行都包含<?php,您可以运行以下命令来清理这些文件:

find * -type f -name "*.php" -exec \
gawk -i inplace 'NR==2 && /^<\?php$/ {next} 1' {} \;

答案2

该解决方案适用于恶意脚本跨越多行的情况,并将使用就地编辑直接更改服务器上的文件。

find /base/path/here -type f -name "*.php" -exec \
sed -Ei '/<\?php/{:l1;/.*\?><\?php/!{N;bl1};s/<\?php.*\?>(<\?php)/\1/}' {} \;

希望这符合要求。

答案3

据我所知,您要删除的所有恶意代码都放在第 1 行中。但请注意,您的<?php标记也放在该行中,因此您应该将整个第一行更改为<?php而不是删除它。

您所需要的只是使用以下命令:

sed -i '1 s/^.*$/<?php/g' yourFile.php

-i选项将就地更改文件。

因此,对于您使用的 find 命令:

find * -type f -name "*.php" -exec sed -i '1 s/^.*$/<?php/g' {} \;

对于第一行和第二行都包含两个标签的文件<?php,需要在运行上述 find 命令后运行以下命令:

find * -type f -name "*.php" -exec perl -ni -e 'print if $. < 1 or $. > 3 or !$seen{$_}++' {} \;

因此它将删除从第 1 行到第 3 行遇到的重复行。-i选项将就地更改文件。

相关内容