2012-02-18 37 views
54

estoy tratando de deobfuscate el siguiente código de Perl (source):¿Cómo deobfusacte correctamente una secuencia de comandos de 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; 

Cuando se ejecuta, imprime Just another genome hacker.

Después de ejecutar el código a través Deparse y perltidy (perl -MO=Deparse jagh.pl | perltidy) el código es el siguiente :

(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; 
} 

Esto es lo que he podido descifrar por mi cuenta.

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

elimina todos los espacios en blanco en $d (la doble hélice).

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

hace un hash con claves como A, T, C y G y como valores 0, 1, 2 y 3. Normalmente código en Python, por lo que esto se traduce en un diccionario {'A': 0, 'B': 1, 'C': 2, 'D': 3} en Python.

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

une las claves del hash con la $;subscript separator for multidimensional array emulation. La documentación dice que el valor predeterminado es "\ 034", lo mismo que SUBSEP en awk, pero cuando lo hago:

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

me da el valor 28? Además, no me queda claro cómo emula esto una matriz multidimensional. ¿Es $p algo así como [['A'], ['T'], ['C'], ['G']] en Python?

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

Mientras $d partidos , ejecutar el código en el bloque de tiempo. pero dado que no entiendo completamente qué es la estructura $p, también me cuesta entender qué sucede aquí.

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

continuar si el la $j módulo 96 es mayor o igual a 16. $j incrementos con cada pasada del bucle while (?).

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

Para $d en el rango 0-3 extraer algunos subcadena, pero en este momento estoy completamente perdido. Las últimas líneas concatenan todo y evalúan el resultado.

+11

Awesome question. – Rayfleck

+16

Siempre debe tener cuidado con el código que 'eval's ofusca las cadenas. He visto una pregunta sinuosa aquí en stackoverflow que finalizó con una evaluación de una cadena que resultó ser '" rm -rf/"'. – TLP

+2

Me recuerda a [Acme :: EyeDrops] (http://p3rl.org/Acme::EyeDrops). –

Respuesta

50

Precaución: no se ejecutan ciegamente Perl ofuscado, sobre todo si hay una eval, acentos abiertos, system, open, etc. llaman en algún lugar que y que podría no ser demasiado obvio*. La eliminación de ofuscación con Deparse y la sustitución cuidadosa de eval s con instrucciones de impresión es imprescindible hasta que comprenda lo que está sucediendo. También se debe considerar ejecutar en una zona de pruebas/con un usuario sin privilegios/en una máquina virtual.

*s&&$_ⅇ evalúa $_ para intance.


Primera observación: 034 es octal. Es igual a 28 (dec) o 0x1c (hex), por lo que no hay nada sospechoso allí.

Lo $; es puramente ofuscación, no puede encontrar una razón para utilizar eso en particular. $p sólo será una cadena A.T.C.G (con . sustituye por $;, sea lo que sea).
Así que en la expresión regular [$p] coincide con cualquiera de {'A', 'T', 'C', 'G', $;}. Como $; nunca aparece en $d, es inútil. A su vez [$p]{4} coincide con cualquier secuencia de cuatro letras en el anterior conjunto, como si se hubiera utilizado (haciendo caso omiso de lo inútil $;):

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

Si tuviera que escribir esto por sí mismo, después de haber eliminado los espacios en blanco, que' d acaba de agarrar cada subcadena sucesiva de $d de longitud cuatro (asumiendo que no hay otros caracteres en $d).

Ahora bien, esta parte es divertido:

foreach $d (0 .. 3) { 
    $c += $a{ substr $1, $d, 1 } * 4**$d; 
} 
  • $1 mantiene el cuatro letras actual punto de código. substr $1, $d, 1 devuelve cada letra sucesiva de ese punto de código.
  • %a mapas A a 00b (binario), T a 01b, 10b a C y G a 11b.

    A 00 
    T 01 
    C 10 
    G 11 
    
  • multiplicando por 4**$d será equivalente a la izquierda un cambio a nivel de bit de 0, 2, 4 y 6.

Así que esta construcción divertida le permite construir cualquier valor de 8 bits en la base- cuatro sistema con ATCG como dígitos!

es decir, que hace las siguientes conversiones:

  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 

Esta parte:

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

hace que la fase de la conversión anterior sólo para los primeros 16 "puntos de código", se salta el próximo 80, a continuación, convierte para los siguientes 16, saltan los próximos 80, etc. Básicamente, se saltan partes de la elipse (sistema de eliminación de ADN basura).


He aquí un texto feo al convertidor de ADN que se puede utilizar para producir cualquier cosa para reemplazar la hélice (no maneja la cosa 80 skip):

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 

Stick $d que en lugar de la hélice (y eliminar la parte que salta en el decodificador).

+8

Ahora, para la pregunta realmente interesante: ¿cómo se escribe el código que convierte el texto en ADN? =) – TLP

+12

Secuencia de comandos de texto a la secuencia de comandos de DNA (sin obscuridad no se parece a la adecuada) suministrada :) – Mat

+5

+1 Muy bien :) Una cosa sobre sus advertencias: La parte 'eval' también se puede ofuscar. El código que mencioné en los comentarios principales usó algo como ';; s ;; $ _; see', que es una doble evaluación en' $ _'. – TLP

Cuestiones relacionadas