Как правильно деобфусактировать скрипт Perl?

56

Я пытаюсь deobfuscate следующий код Perl (источник):

#!/usr/bin/perl
(my$d=q[AA                GTCAGTTCCT
  CGCTATGTA                 ACACACACCA
    TTTGTGAGT                ATGTAACATA
      CTCGCTGGC              TATGTCAGAC
        AGATTGATC          GATCGATAGA
          ATGATAGATC     GAACGAGTGA
            TAGATAGAGT GATAGATAGA
              GAGAGA GATAGAACGA
                TC GATAGAGAGA
                 TAGATAGACA G
               ATCGAGAGAC AGATA
             GAACGACAGA TAGATAGAT
           TGAGTGATAG    ACTGAGAGAT
         AGATAGATTG        ATAGATAGAT
       AGATAGATAG           ACTGATAGAT
     AGAGTGATAG             ATAGAATGAG
   AGATAGACAG               ACAGACAGAT
  AGATAGACAG               AGAGACAGAT
  TGATAGATAG             ATAGATAGAT
  TGATAGATAG           AATGATAGAT
   AGATTGAGTG        ACAGATCGAT
     AGAACCTTTCT   CAGTAACAGT
       CTTTCTCGC TGGCTTGCTT
         TCTAA CAACCTTACT
           G ACTGCCTTTC
           TGAGATAGAT CGA
         TAGATAGATA GACAGAC
       AGATAGATAG  ATAGAATGAC
     AGACAGAGAG      ACAGAATGAT
   CGAGAGACAG          ATAGATAGAT
  AGAATGATAG             ACAGATAGAC
  AGATAGATAG               ACAGACAGAT
  AGACAGACTG                 ATAGATAGAT
   AGATAGATAG                 AATGACAGAT
     CGATTGAATG               ACAGATAGAT
       CGACAGATAG             ATAGACAGAT
         AGAGTGATAG          ATTGATCGAC
           TGATTGATAG      ACTGATTGAT
             AGACAGATAG  AGTGACAGAT
               CGACAGA TAGATAGATA
                 GATA GATAGATAG
                    ATAGACAGA G
                  AGATAGATAG ACA
                GTCGCAAGTTC GCTCACA
])=~s/\s+//g;%a=map{chr $_=>$i++}65,84,67,
71;$p=join$;,keys%a;while($d=~/([$p]{4})/g
){next if$j++%96>=16;$c=0;for$d(0..3){$c+=
$a{substr($1,$d,1)}*(4**$d)}$perl.=chr $c}
             eval $perl;

При запуске он выводит Just another genome hacker.

После запуска кода Deparse и perltidy (perl -MO=Deparse jagh.pl | perltidy) код выглядит следующим образом:

( my $d =
"AA...GCTCACA\n" # snipped double helix part
) =~ s/\s+//g;
(%a) = map( { chr $_, $i++; } 65, 84, 67, 71 );
$p = join( $;, keys %a );
while ( $d =~ /([$p]{4})/g ) {
    next if $j++ % 96 >= 16;
    $c = 0;
    foreach $d ( 0 .. 3 ) {
        $c += $a{ substr $1, $d, 1 } * 4**$d;
    }
    $perl .= chr $c;
}

Вот то, что я смог расшифровать самостоятельно.

( my $d =
"AA...GCTCACA\n" # snipped double helix part
) =~ s/\s+//g;

удаляет все пробелы в $d (двойная спираль).

(%a) = map( { chr $_, $i++; } 65, 84, 67, 71 );

делает хэш с помощью клавиш A, T, C и G и как значения 0, 1, 2 и 3. Я обычно код в Python, так что это переводит в словарь {'A': 0, 'B': 1, 'C': 2, 'D': 3} в Python.

$p = join( $;, keys %a );

соединяет ключи хеша с $; разделителем индексов для многомерной эмуляции массива. В документации говорится, что по умолчанию "\ 034", то же, что и SUBSEP в awk, но когда я это делаю:

my @ascii = unpack("C*", $p);
print @ascii[1];

Получаю значение 28? Кроме того, мне непонятно, как это эмулирует многомерный массив. Является ли $p теперь что-то вроде [['A'], ['T'], ['C'], ['G']] в Python?

    while ( $d =~ /([$p]{4})/g ) {

Пока $d соответствует ([$p]{4}), выполните код в блоке while. но поскольку я не совсем понимаю, что такое структура $p, мне также трудно понять, что здесь происходит.

next if $j++ % 96 >= 16;

Продолжайте, если модуль $j по модулю 96 больше или равен 16. $j увеличивается с каждым проходом цикла while (?).

$c = 0;
foreach $d ( 0 .. 3 ) {
    $c += $a{ substr $1, $d, 1 } * 4**$d;
}

Для $d в диапазоне от 0 до 3 извлеките некоторую подстроку, но в этот момент я полностью потерян. Последние несколько строк конкатенируют все и оценивают результат.

  • 11
    Внушительный вопрос.
  • 16
    Вы всегда должны быть осторожны с кодом, который eval запутанные строки. Здесь я видел хитрый вопрос о стекапровороте, который закончился "rm -rf /" строки, которая оказалась "rm -rf /" .
Показать ещё 1 комментарий
Теги:
deobfuscation

1 ответ

48
Лучший ответ

Предостережение: не слепо запускать запутанный perl, особенно если есть eval, backticks, system, open и т.д. вызывать где-то в нем , и это может быть не слишком очевидно *. De-obfuscating с Deparse и тщательной заменой eval заявлениями печати является обязательным, пока вы не поймете, что происходит. Следует также учитывать запуск в песочнице/с непривилегированным пользователем/в виртуальной машине.

*s&&$_ⅇ оценивает $_ для intance.


Первое наблюдение: 034 - восьмеричное. Он равен 28 (dec) или 0x1c (hex), поэтому нет ничего подозрительного.

Вещество $; является чисто обфускацией, не может найти причины использовать это в частности. $p будет просто строкой A.T.C.G (с заменой . на $;, что бы это ни было).
Поэтому в regex [$p] соответствует любой из {'A', 'T', 'C', 'G', $;}. Поскольку $; никогда не появляется в $d, это бесполезно. В свою очередь, [$p]{4} соответствует любой последовательности из четырех букв в приведенном выше наборе, как если бы это использовалось (игнорируя бесполезный $;):

while ( $d =~ /([ATCG]{4})/g ) { ... }

Если вам пришлось написать это самостоятельно, удалив пробел, вы просто возьмете каждую последующую подстроку $d длиной четыре (при условии, что в $d нет других символов.)

Теперь эта часть весело:

foreach $d ( 0 .. 3 ) {
    $c += $a{ substr $1, $d, 1 } * 4**$d;
}
  • $1 содержит текущий четырехбуквенный код. substr $1, $d, 1 возвращает каждую последовательную букву из этого кодового пункта.
  • %a отображает A в 00b (двоичный), T в 01b, C в 10b и G в 11b.

    A   00
    T   01
    C   10
    G   11
    
  • умножение на 4**$d будет эквивалентно побитовому сдвигу влево 0, 2, 4 и 6.

Итак, эта забавная конструкция позволяет вам построить любое значение 8 бит в системе base-four с ATCG как цифры!

то есть. он выполняет следующие преобразования:

         A A A A
AAAA -> 00000000

         T A A T
TAAT -> 01000001 -> capital A in ascii

         T A A C
CAAT -> 01000010 -> capital B in ascii

CAATTCCTGGCTGTATTTCTTTCTGCCT -> BioGeek

Эта часть:

next if $j++ % 96 >= 16;

делает указанное преобразование выполненным только для первых 16 "кодовых точек", пропускает следующие 80, затем преобразует в течение следующих 16, пропускает следующие 80 и т.д. Он по существу просто пропускает части эллипса (система удаления нежелательной ДНК).


Вот уродливый текст для конвертера ДНК, который вы могли бы использовать для создания чего-либо, чтобы заменить спираль (не обрабатывает вещь 80):

use strict;
use warnings;
my $in = shift;

my %conv = ( 0 => 'A', 1 => 'T', 2 => 'C', 3 => 'G');

for (my $i=0; $i<length($in); $i++) {
    my $chr = substr($in, $i, 1);
    my $chv = ord($chr);
    my $encoded ="";
    $encoded .= $conv{($chv >> 0) & 0x3};
    $encoded .= $conv{($chv >> 2) & 0x3};
    $encoded .= $conv{($chv >> 4) & 0x3};
    $encoded .= $conv{($chv >> 6) & 0x3};
    print $encoded;
}
print "\n";
$ perl q.pl 'print "BioGeek\n";'
AAGTCAGTTCCTCGCTATGTAACACACACAATTCCTGGCTGTATTTCTTTCTGCCTAGTTCGCTCACAGCGA

Вставьте в $d, что вместо спирали (и удалите часть пропуска в декодере).

  • 8
    Теперь по-настоящему интересный вопрос: как вы пишете код, который превращает текст в ДНК? знак равно
  • 12
    Сценарий «Текст в ДНК» (настолько прост, что он не выглядит как настоящий perl) :)
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню