ienrikex
Usuario (Venezuela)

Hola Taringueros!!! Hay mucha gente haciendo peticion sobre las distintas formas de hackear redes wifi , saber claves WPA , WPE etc.. Bueno, para los que tenemos nuestro router wifi, y no queremos que algun extraño se meta en nuestro internet, pagado por nosotros con esfuerzo, aqui van algunas notas de seguridad La seguridad en redes wireless está enfocada de variadas maneras: - acceso y el transporte de datos fuertemente protegidos con protocolos como SSH - SSH y redes privadas virtuales - protección de acceso con contraseña - sólo cifradoio de datos, etc, etc - SSL y IPSEC - WEP - protocolos para la autenticación de usuarios en redes wireless (EAP): http://www.nwfusion.com/news/tech/2001/0924tech.html El estándar 802.11 provee de un sistema de cifrado "Wired Equivalent Privacy" (WEP), que es un protocolo para redes Wirelessque permite encriptar la información que se transmite. Proporciona encriptación a nivel 2, al contrario que otros protocolos como IPSEC (nivel 3 o SSL (nivel 4). Aunque hay que decir que esta poco implantado, la mayoría no lo activa. Si, es verdad que es un sistema fácil de romper, pero supone una primera y básica barrera que no se puede menospreciar. Este mismo estándar utilizando protocolos avanzados como el EAP-TTS, TTLS, etc, el cual fundamentalmente se basa en autentificar dispositivos mediante el concepto de certificados digitales, criptografía asimétrica, etc, es otro manera de implementar una buena seguridad. Este sistema es reemplazado por el sistema Wi-Fi Protected Access o WPA que ofrece métodos más robostos para el cifrado y la autenticación. El protocolo WEP está basado en el algoritmo de encriptación RC4, y utiliza claves de 64bits o de 128bits. En realidad son de 40 y 104 bits, ya que los otros 24 bits van en el paquete como Vector de Inicialización (IV). Se utiliza un checksum para prevenir que se inyecten paquetes spoofeados. Otros elementos complementarios para la autentificación de usuarios pueden ser RADIUS, TACACS+LDAP, etc. Ataques que sufren este tipo de redes: - Ataques al protocolo WEB. Fuerca bruta. - Ataque Inductivo Arbaugh - Asociados a debilidades en el algoritmo key Scheduling de RC4 - Descubrimientode ESSID ocultos - Denegación de servicio - Ataues del tipo "Man in the middle" - Romper filtrado basado en direcciones - Envenenamiento de la cache ARP. Surgen herramientas para, por ejemplo, olfatear el "aire" con AirSnort, un sniffer para redes wireless y que aprovecha, junto a otras herramientas las debilidades del sistema WEP: http://www.virusprot.com/Nt240821.html Podemos también auditar redes wireless com NetStumbler desde un sistema W32: NetStumbler ó escanear con Wireless Scanner: Wireless Scanner También podemos dotar a nuestro sistema o red wireless de un IDS o sistema de detección de intrusos con AirDefense IDS. Y que mejor que un manual práctico, aunque sea en inglés, sobre la seguridad en este tipo de redes: "Security Practicum: Essential Home Wireless Security Practices": http://arstechnica.com/paedia/w/wireless-security-howto/home-802.11b-1.html Los famosos símbolos para indicar los accesos a redes wireless: Para estar al tanto de la tecnología sin cables: http://www.sincables.net/ Enlaces sobre WEP: Vulnerabilidad WEP. http://www-ma2.upc.es/~cripto/Q1-02-03/wep.pdf Seguridad ( o inseguridad) del algoritmo WEP. http://www.redlibre.net/wiki/moin.cgi/Vulnerabilidad_20WEP Sobre WEP. http://www.isaac.cs.berkeley.edu/isaac/wep-faq.html WEP. Configuración de la seguridad: Guía del usuario del adaptador Mini PCI para red local Intel(R) PRO/Wireless 7100 y 2100 3A http://support.jp.dell.com/docs/network/p51814/sp/wepsetup.htm Algunos consejos. - Deshabilitar el SSID broadcast. El SSID es el nombre de nuestra red. Si no conocieramos ni el SSID ni la claves wep, nos sería muy dificil entrar en esa red wireless. Muchos aparatos tienen activado por defecto, que publiquen ese nombre de red en todas las conexiones. - Filtrado por direcciones MAC. Aqui lo que hacemos es permitir que solo las tarjetas inalambricas que queramos puedan acceder, aunque siempre se puede piratear una dirección MAC. - Activar las claves de cifrado WEP y cambiarlas con regularidad, a costa de perder velocidad en la transmisión de datos. - Protejer las unidades y carpetas con contraseñas. - Implemente un sistema de red privada virtual (VPN) para aumentar la seguridad. La mayoría de los sistemas operativos incluyen un cliente VPN. Sobre WPA y TKIP. Para mejorar la criptografía de los datos, WPA utiliza su Temporal Key Integrity Protocol (TKIP), que, encaminando todas las conocidas debilidades del WEP, proporciona respuestas a las mismas con: • Una función de per-packet key mixing • Un control sobre la integridad del mensaje • Un “Initialization Vector” ampliado con reglas de secuencia • Un mecanismo de re-keying Pero que es eso de TKIP. La WECA (una alianza entre las mas importantes empresas que fabrican productos informáticos, que se encarga de certificar que el producto final sea 100% compatible con el estandar) (http://www.wi-fi.org/) está trabajando con una nuevo sistema de encriptación, la encriptación TKIP (Temporal Key Integrity Protocol). Básicamente las mejoras de esta encriptación es que tiene una gestión dinámica de las claves de cifrado, asignando a cada conexión una clave de cifrado diferente (ya no es estática) y además de eso, encriptación de cada paquete que se envie. La ventaja del TKIP es que es 100% compatible ocn el hardware actual a diferencia del EAP Detectando Sniffers en nuestra red. Redes conmutadas y no conmutadas. Vamos a tratar aquí, principalmente, la detección de sniffers en nuestra red desde el escenario más básico posible. Este escenarío sería una subred o red no conmutada. Aunque más adelante nos introduciremos brévemente en la escuha en redes conmutadas o basadas en switches y herramientas de detección en este tipo de redes. Antes que nada, decir que los sniffers no son fáciles de detectar y combatir, ya que se trata de programas que trabajan en modo pasivo. Las técnicas que se tratan aquí, por tanto, no son totalmente fiables, aunque en algunos casos si suponen una grn aproximación al descubrimiento de este tipo de software. Antes que nada y para enteder algunos coneceptos de este artículo veremos como funciona, brevemente, el protocolo ARP. Que es. Para que sirve ARP ? En una red Ethernet cuando queremos enviar un paquete IP entre dos hosts conectados las únicas direcciones válidas son las MAC y lo que circula son tramas Ethernet. Entonces y volviendo al ejemplo de antes cuando queremos enviar un paquete IP lo que se hace es meter el paquete dentro de una trama Ethernet y enviar. Formato de una cabecera ARP: HLEN Longitud dirección hardware PLEN Longitud dirección del protocolo OPERACION Código de operación (ARPreques ó ARPreply) SENDER HA Dirección de origen hardware SENDER IP Dirección de origen del protocolo TARGET HA Dirección de destino hardware Cual es el problema entonces ? El problema radica en que que sabemos la dirección IP del host de destino pero no su dirección MAC. Como se soluciona esto ? La solución está en que antes de enviar el paquete IP se debe usar ARP para averiguar cual es la dirección MAC del host destino de la conección que pretendemos realizar. Y como se hace ?. ARP tiene dos tipos básicos de mensajes: - mensaje de peticion o ARPrequest - mensaje de respuesta o ARPreply los dos viajan por nuestra red dentro de tramas Ethernet. Cuando queremos enviar un paquete IP desde un host origen (A) hacia un host destino (B) sucede: (A) crea un mensaje o petición ARPrequest indicando: - su dirección IP - su dirección MAC - dirección IP del host (B) - campo de dirección MAC host (B) sin rellenar. envia el ARPrequest a la dirección broadcast (todos los hosts de la red) pero sólo contesta uno de ellos (B). Entonces: (B) crea un mensaje ARPreply: - rellena el campo de dirección MAC con su MAC - intercambia las direcciones origen y destino - cambia el tipo de mensaje de ARPreques a ARPreply - envia el mesnaje ARPrpely a (A). Ya hay entonces información suficiente para establecer cualquier comunicación entre (A) y (B). Esto lo podemos comprobar utilizando un sniffer de red como Ethereal y filtrando por protocolos, en este caso ARP: C:scan>windump -qtn arp windump: listening on DeviceNPF_{604C8AE3-5FAC-45A5-BFAA-81175A8C32BF} arp who-has 192.168.5.241 tell 192.168.5.240 arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.5.4 tell 192.168.5.240 arp who-has 192.168.5.6 tell 192.168.5.240 arp who-has 192.168.5.44 tell 192.168.5.240 arp who-has 192.168.5.14 tell 192.168.5.240 arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.4.15 tell 192.168.4.10 arp reply 192.168.4.15 is-at 0:1:2:e7:57:cf arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.4.15 tell 192.168.4.1 arp reply 192.168.4.15 is-at 0:1:2:e7:57:cf arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.4.15 tell 192.168.4.13 arp reply 192.168.4.15 is-at 0:1:2:e7:57:cf..... Toda la información de las relaciones IP/MAC se guarda en la cache ARP. En un sistema Windows: C:>arp -a Interfaz: 192.168.4.3 on Interface 0x1000003 Dirección IP Dirección física Tipo 192.168.4.1 00-04-76-97-b3-a9 dinámico 192.168.4.20 00-a0-24-4e-4e-4e dinámico Sistemas Linux: $ arp -a serprint (192.168.4.2) at 52:54:05:fd:de:e5 infografia3 (192.168.4.3) at 00:90:27:6a:58:74 Una vez visto como funciona el protocolo ARP, seguimos con la detección de los sniffers. Detección en sistemas UNIX/Linux En entornos Linux o UNIX la verificación de una interface en modo promiscuo se puede hacer usando ifconfig. Este programa configura la interface de red instalada en un determinado host y obtiene información de la configuración en el momento de ejecutar el programa. Cuando un adaptador de red se encuentra en modo promiscuo, ifconfig nos devuelve la siguiente información: $ ifconfig -a eth0 Link Encap: 10Mbps Ethernet HWaddr: xx:xx:xx:xx:xx:xx inet addr: a.b.c.d Bcast: a.b.c.f Mask: m.m.m.m UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1 (OJO: Modo promiscuo) RX packets: 0 errors:0 dropped:0 overruns:0TX packets:0 errors:0 dropped:0 overruns:0 Interrupt:15 Base Address:0x300 Este sistema no es infalible. Existen programas que pueden hacer esta labor como: cpm (Check Promiscuous Mode) Este pequeño programa realizado por la Universidad de Carnegie Mellon, chequea el interfaz de red de la máquina descubriendo si está siendo utilizado en modo promiscuo (escuchando todo el tráfico de la red). $ cpm 4 network interfaces found: eth0:5: Normal eth0:3: Normal eth0:2: Normal eth0:1: Normal eth0: *** IN PROMISCUOUS MODE *** Existen otros programas como Antisniff, Sentinel, SniffDet, ifstatus o NEPED: Veamos como trabaja NEPED Tenemos que introducir la interface de red: $ neped eth0 ---------------------------------------------------------- > My HW Addr: 00:50:BF:1C:41:59 > My IP Addr: 192.168.0.1 > My NETMASK: 255.255.255.0 > My BROADCAST: 192.168.1.255 ---------------------------------------------------------- Scanning .... * Host 192.168.0.3, 00:C2:0F:64:05F **** Promiscuous mode detected !!! End. NEPED utiliza la técnica de realizar una simple petición ARP para cada una de las IPs de la red a diagnosticar, pero ojo, los paquetes no van destinados a broadcast (FFFFFFF), sino a una dirección aleatoria e inexistente. Sólo las interfaces en modo promiscuo verán estos paquetes, y de esta manera, sólo estas interfaces contestarán a estas peticiones. Existe también un dispositivo de hardware llamado Tap. Este dispositivo permite conectarse a un Hub o incluso a un switch de red al cual conectásemos un dispositivo (ordenador) para monitorizar la red. Existen tipos de Taps para cada tipo de red Ethernet 10 Mbps, 100 Mbps y 1 Gbps. Más información en: www.netoptics.com SniffDet - Remote Sniffer Detection http://prdownloads.sourceforge.net/sniffdet/sniffdet-0.9.tar.gz Usa lás técnicas test ICMP, test ARP, test DNS y test de ping de latencia. # ./sniffdet 0.9 A Remote sniffer Detection Tool Copyright (c) 2003 Ademar de Souza Reis Jr. Milton Soares Filho Usage: ./sniffdet [options] TARGET Where: TARGET is a canonical hostname or a dotted decimal IPv4 address -i --iface=DEVICE Use network DEVICE interface for tests -c --configfile=FILE Use FILE as configuration file -l --log=FILE Use FILE for tests log -f --targetsfile=FILE Use FILE for tests target --pluginsdir=DIR Search for plugins in DIR -p --plugin=FILE Use FILE plugin -u --uid=UID Run program with UID (after dropping root) -g --gid=GID Run program with GID (after dropping root) -t --test=[testname] Perform specific test Where [testname] is a list composed by: dns DNS test arp ARP response test icmp ICMP ping response test latency ICMP ping latency test -v --verbose Run in verbose mode -h, --help Show this help screen and exit --version Show version info and exit Defaults: Interface: "eth0" Log file: "sniffdet.log" Config file: "/etc/sniffdet.conf" Plugins Directory: "/usr/lib/sniffdet/plugins" Plugin: "stdout.so" You have to inform at least one test to perform vemos un ejemplo resultado de este software: ------------------------------------------------------------ Sniffdet Report Generated on: xxxxxxxxx 2003 ------------------------------------------------------------ Tests Results for target 192.168.2.1 ------------------------------------------------------------ Test: ARP Test Check if target replies a bogus ARP request (with wrong MAC) Validation: OK Started on: xxxx Finished on: Mxxxxx Bytes Sent: 84 Bytes Received: 60 Packets Sent: 2 Packets Received: 1 ------------------------------------------------------------ RESULT: POSITIVE ------------------------------------------------------------ ------------------------------------------------------------ Number of tests with positive result: #1 ------------------------------------------------------------ AntiSniff_v1.3 http://www.l0pht.com/antisniff Esta herramienta, tanto para plataformas linux/Unix como para Win32, es muy sencilla de usar y tan sólo es necesario inroducir el rango ede IPs a monitorizar en busca del posible sniffer. Usa las técnicas de ping de latencia, test DNS y test ARP. Sentinel http://www.packetfactory.net/Projects/sentinel/ Utiliza los métodos de: test DNS, test ARP, prueba ICMP Etherping, y ping de latencia. Uso de sentinel: ./sentinel [método] [-t <destino ip>] Métodos: [ -a test ARP ] [ -d test DND ] [ -i ICMP Test ping de latencia] [ -e ICMP test Etherpingt ] Opciones: [ -f <fichero> fichero o IP] [ -c <x.x.x> clase C a monitorizar] [ -n <úmero de paquetes a enviar> ] [ -I <dispositivo> ] Ejemplos: ./sentinel -a -t 192.168.1.2 Optimizado para usar el test ARP host 192.168.1.2 ./sentinel -d -f 1.1.1.1 -t 192.168.1.2 Optimizado para usar el test DNS host 192.168.1.2 ./sentinel -aed -c 10.2.2 Optimizado para escanear una red de clase c (10.2.2) usando el test ARP, DNS y test Etherping Optimizado para usar el test DNS host 192.168.1.2 Otras formas de detectar posibles sniffers * Detectar y controlar los logs que suelen generar los sniffers. * Detectar y controlar las conexiones al exterior. * Monitorizados los programas que acceden al dispositivo de red. * Normalmente una interface en modo promiscuo, queda reflejada en el fichero de logs: * $ cat /var/log/messages Otras técnicas de detección Sólo por nombrar algunas, son usadas por los programas anti-sniffers. Comentaremos la última: * Ping de latencia * Test ARP * Uso de un IDS. Por ejemplo Snort que contiene un preprocesador (arpspoof) que nos puede servir. Aquí las líneas de snort.conf configurando el preprocesador: # arpspoof #---------------------------------------- # Experimental ARP detection code from Jeff Nathan, detects ARP attacks, # unicast ARP requests, and specific ARP mapping monitoring. To make use # of this preprocessor you must specify the IP and hardware address of hosts on # the same layer 2 segment as you. Specify one host IP MAC combo per line. # Also takes a "-unicast" option to turn on unicast ARP request detection. # Arpspoof uses Generator ID 112 and uses the following SIDS for that GID: # SID Event description # ----- ------------------- # 1 Unicast ARP request # 2 Etherframe ARP mismatch (src) # 3 Etherframe ARP mismatch (dst) # 4 ARP cache overwrite attack preprocessor arpspoof preprocessor arpspoof_detect_host: 192.168.2.1 f0:0f:00:f0:0f:00 Otro IDS para sistemas Linux como Prelude Hybrid IDS (http://www.preludeids.org/rubrique.php3?id_rubrique=13), poseee un plugin ( ArpSpoof Plugin ) que nos ayuda a detectar incoherencias en mensajes ARP, conflicos con una base de datos ARPwatch (veremos esto más adelante), etc: Configuración de plugin: /usr/local/etc/prelude-nids/prelude-nids.conf ... [ArpSpoof] # # Search anomaly in ARP request. # # The "directed" option will result in a warn each time an ARP # request is sent to an address other than the broadcast address. # # directed; # arpwatch=<ip> <macaddr>; ... * Test DNS Las técnicas de detección. Breve explicación. El test DNS En este método, la herramienta de detección en sí misma está en modo promíscuo. Creamos numerosas conexiones TCP falsas en nuestro segmento de red, esperando un sniffer pobremente escrito para atrapar estas conexiones y resolver la direción IP de los inexistentes hosts. Algunos sniffers realizan búsquedas inversas DNS en los paquetes uqe capturan. Cuando se realiza una búsqueda inversa DNS, un utilidad de deteción de sniffers "huele" la petición de las operaciones de búsqueda para ver si el objetivo es aquel que realiza la petición del host inexistente. El Test del Ping Este método confia en un problema en el núcleo de la máquina receptora. Podemos construir una petición tipo "ICMP echo" con la dirección IP de la máquina sospechosa de hospedar un sniffer, pero con una dirección MAC deliberadamente errónea. Enviamos un un pacquete "ICMP echo" al objetivo con la dirección IP correcta, pero con una dirección de hardware de destino distinta. La mayoría de los sistemas desatenderán este paquete ya que su dirección MAC es incorrecta. Pero en algunos sistemas Linux, NetBSD y NT, puesto que el NIC está en modo promíscuo, el sniffer asirá este paquete de la red como paquete legítimo y responderá por consiguiente. Si el blanco en cuestión responde a nuestra petición, sabremos que está en modo promíscuo. Un atacante avanzado puede poner al día sus sniffers para filtrar tales paquetes para que parezca que el NIC no hubiera estado en modo promíscuo. El Test ICMP Ping de Latencia. En éste método, hacemos ping al blanco y anotamos el Round Trip Time (RTT, retardo de ida y vuelta o tiempo de latencia) Creamos centenares de falsas conexiones TCP en nuestro segmento de red en un período de tiempo muy corto. Esperamos que el sniffer esté procesando estos paquetes a razón de que el tiempo de latencia incremente. Entonces hacemos ping otra vez, y comparamos el RTT esta vez con el de la primera vez. Despues de una serie de tests y medias, podemos concluir o no si un sniffer está realmente funcionando en el objetivo o no. El test ARP Podemos enviar una petición ARP a nuestro objetivo con toda la información rápida excepto con una dirección hardware de destino errónea. Una máquina que no esté en modo promíscuo nunca verá este paquete, puesto que no era destinado a ellos, por lo tanto no contestará. Si una máquina está en modo promiscuo, la petición ARP sería considerada y el núcleo la procesaría y contestaría. Por la máquina que contesta, la sabemos estamos en modo promiscuo. El test Etherping Enviamos un "ping echo" al host a testear con una IP de destivo correcta y dirección MAC falseada. Si el host responde, es que su interfaz está en modo promiscuo, es decir, existe un sniffer a la escucha y activo. Protegerse contra la acción de los sniffers A grandes rasgos para protegernos de los sniffers y para que éstos no cumplan sus objetivos de olfateo de contraseñas y en general nos "lean datos sensibles" en texto plano -sin cifrado fuerte-, podemos hacer uso de diversas técnicas o utilizar sistemas como: * Redes conmutadas (no siempre es efectivo) * PGP * SSL * SSH * VPN, * etc. Aunque ya veremos más adelante que ni siquiera el uso de SSH, por citar un ejemplo, nos puede protejer efectivamente del uso de ciertos tipos de sniffer como ettercap. Detección en sistemas Windows PromiScan "PromiScan (www.securityfriday.com) es una utilidad de distribución gratuita diseñada para dar caza a los nodos promiscuos en una LAN rápidamente y sin crear una carga pesada en la red. Hay que tener en cuenta que localizar un nodo promiscuo es una tarea ardua, y que en muchos casos el resultado es incierto; no obstante, PromiScan consigue mostrar cada uno de esos nodos de una manera transparente, claramente visible. Para usar PromiScan es necesario contar con Windows 2000 Professional y haber instalado previamente el controlador WinPcap." http://www.securityfriday.com/ToolD...iscan_003.html. PromiscDetect C:scan>promiscdetect PromiscDetect 1.0 - (c) 2002, Arne Vidstrom ([email protected]) - http://ntsecurity.nu/toolbox/promiscdetect/ Adapter name: - NIC PCI 3Com EtherLink XL 10/100 PCI para administraci¾n completa del equipo (3C905C-TX) Active filter for the adapter: - Directed (capture packets directed to this computer) - Multicast (capture multicast packets for groups the computer is a member of) - Broadcast (capture broadcast packets) - Promiscuous (capture all packets on the network) WARNING: Since this adapter is in promiscuous mode there could be a sniffer running on this computer! http://www.ntsecurity.nu/cgi-bin/do...scdetect.exe.pl http://ntsecurity.nu/downloads/promiscdetect.exe ProDETECT 0.2 BETA http://sourceforge.net/projects/prodetect/ http://prdownloads.sourceforge.net/prodetect/proi386.exe?download Alerta de ProDETECT: Detección en redes conmutadas En redes commutas o que hagan uso de switches, la técnica de ARP poisoning o envenenamiento arp es la más efectiva. Esta técnica consiste, muy brevemente, en modificar (envenenar) la tabla ARP de los host involucrados en el ataque para que éstos envíen a la red tramas Ethernet con destino la MAC del atacante. Esto significa que el switch entregará los datos de las comunicación a dicho host. Para evitar el refresco de la caché ARP es necesario el envio constante de arp-reply. Una posible solución o defensa sería el uso de MACs estáticas, con el fin de que no puedan ser modificadas, aunque en algunos sistemas Windows esto no es eficiente al 100 por 100. En sistemas Linux la herramienta ARPWatch ( http://www-nrg.ee.lbl.gov/ ) nos puede servir para detectar el uso del envenenamiento ARP en nuestro sistema. Con ARPWatch podemos comprobar la correspondencia entre pares IP-MAC (Ethernet). En caso de que un cambio en un par se produzca (esto es, se escuche en el interfaz de red del sistema), ARPWatch envía un correo de notificación del suceso a la cuenta root o administrador del sistema con un mensaje tipo "FLIP FLOP o Change ethernet address". También podemos monitorizar la existencia de nuevos host ( aparición de una nueva MAC en la red). # ./arpwatch -? Version 2.1a11 usage: arpwatch [-dN] [-f datafile] [-i interface] [-n net[/width]] [-r file] [-u username] [-e username] [-s username] # cat /etc/sysconfig/arpwatch # -u <username> : defines with what user id arpwatch should run # -e <email> : the <email> where to send the reports # -s <from> : the <from>-address OPTIONS="" Una herramienta similar a ARPwatch pero para sistemas Windows la encontramos en WinARP Watch v1.0 (http://www.securityfocus.com/data/tools/warpwatch.zip). Esta herramienta no enviará correo alguno a ningún administrador, pero nos tendrá puntualmente informados sobre la caché ARP, las correspondencias IP/MAC, cualquier nuevo par que se añada a la caché, etc. Una alerta de WinARP Watch: Existe en el mercado un tipo especial de switches que está preparados para que la tabla ARP no pueda ser modificada. Hablando de herramientas, una que realiza este trabajo de escucha en redes conmutadas con gran eficacia es ettercap. Ettercap ( http://ettercap.sourceforge.net ) es capaz de escuchar tanto redes basadas en hubs como en switches. Además puede escuchar conexiones SSH e incluso detectar otros envenenamientos o modificaciones de la tabla ARP. Detección de envenenamiento ARP con ettercap en un sistema Windows. C:...ettercap>ettercap -Nc ettercap 0.6.b (c) 2002 ALoR & NaGA List of available devices : --> [dev0] - [3Com EtherLink PCI] Please select one of the above, which one ? [0]: Your IP: 192.168.4.3 with MAC: 00:04:762:C9:5F on Iface: dev0 Building host list for netmask 255.255.255.0, please wait... Sending 255 ARP request... * |==================================================>| 100.00 % Resolving 14 hostnames... * |==================================================>| 100.00 % Checking for poisoners... MAC of 192.168.4.59 and 192.168.4.235 are identical ! Otra herramienta que detecta cambios en los pares IP/MAC así como ataques tipo arp-spoofinges ACiD (ARP Change intrusion Detection) : C:scanACID>acid ACiD - 0.0.2 - (c) 2002 Roberto Larcher - [email protected] All rights reserved. Press CTRL+C to stop. Initializing default adapter. Please wait... IP: 0.4.168.192 Subnet Mask: 0.255.255.255 Network type: Ethernet ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.2.3 00:a0:24:4d:bc:69 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.2.3 00:a0:24:4d:bc:69 ACiD: bogon 192.168.2.3 00:a0:24:4d:bc:69 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.20 00:a0:24:4e:4e:4e ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.15 00:01:02:e7:57:cf ACiD: bogon 192.168.4.10 00:a0:24:4e:51:6b ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.4.3 00:04:76:f2:c9:5f ACiD: bogon 192.168.4.3 00:04:76:f2:c9:5f ACiD: bogon 192.168.4.20 00:a0:24:4e:4e:4e ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.4.20 00:a0:24:4e:4e:4e ACiD: bogon 192.168.4.15 00:01:02:e7:57:cf ACiD: bogon 192.168.4.8 00:10:4b:4d:15:bb Ctrl+C detected... IP <-> MAC table: 192.168.2.3 00:a0:24:4d:bc:69 192.168.4.1 00:04:76:97:b3:a9 192.168.4.10 00:a0:24:4e:51:6b 192.168.4.15 00:01:02:e7:57:cf 192.168.4.20 00:a0:24:4e:4e:4e 192.168.4.3 00:04:76:f2:c9:5f 192.168.4.5 00:04:76:9a:66:a6 192.168.4.8 00:10:4b:4d:15:bb 192.168.5.240 00:06:5b:05:9a:e7 ArpCount table: 192.168.2.3 -3 192.168.4.1 -8 192.168.4.10 1 192.168.4.15 -2 192.168.4.20 3 192.168.4.3 -2 192.168.4.5 -10 192.168.4.8 1 192.168.5.240 -6 En la consola de ACID si existe un error en la paridad IP/MAC nos alertará de esta manera: ACiD: bogon 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: ethernet mismatch 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: bogon 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: ethernet mismatch 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: bogon 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: ethernet mismatch 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: bogon 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: ethernet mismatch 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 Possible spoof 192.168.4.5 00:04:76:9a:66:a6 was at 00:04:76:f2:c9:5f - . -

Hola taringueros !, vengo con este post porque hay mucha gente haciendo peticiones sobre programas para descifrar y hackear redes wi-fi, pero los que tenemos router wifi, tenemos que proteger nuestros routers , pero nada parece funcionar... nosotros pagamos con esfuerzo, por eso hice este post , un post para reforzar el 97% tu router, ni el mas experto hack podra entrar a la red, 100% comprobado con 4 routers en mi casa =D Disfruten La seguridad en redes wireless está enfocada de variadas maneras: - acceso y el transporte de datos fuertemente protegidos con protocolos como SSH - SSH y redes privadas virtuales - protección de acceso con contraseña - sólo cifradoio de datos, etc, etc - SSL y IPSEC - WEP - protocolos para la autenticación de usuarios en redes wireless (EAP): http://www.nwfusion.com/news/tech/2001/0924tech.html El estándar 802.11 provee de un sistema de cifrado "Wired Equivalent Privacy" (WEP), que es un protocolo para redes Wirelessque permite encriptar la información que se transmite. Proporciona encriptación a nivel 2, al contrario que otros protocolos como IPSEC (nivel 3 o SSL (nivel 4). Aunque hay que decir que esta poco implantado, la mayoría no lo activa. Si, es verdad que es un sistema fácil de romper, pero supone una primera y básica barrera que no se puede menospreciar. Este mismo estándar utilizando protocolos avanzados como el EAP-TTS, TTLS, etc, el cual fundamentalmente se basa en autentificar dispositivos mediante el concepto de certificados digitales, criptografía asimétrica, etc, es otro manera de implementar una buena seguridad. Este sistema es reemplazado por el sistema Wi-Fi Protected Access o WPA que ofrece métodos más robostos para el cifrado y la autenticación. El protocolo WEP está basado en el algoritmo de encriptación RC4, y utiliza claves de 64bits o de 128bits. En realidad son de 40 y 104 bits, ya que los otros 24 bits van en el paquete como Vector de Inicialización (IV). Se utiliza un checksum para prevenir que se inyecten paquetes spoofeados. Otros elementos complementarios para la autentificación de usuarios pueden ser RADIUS, TACACS+LDAP, etc. Ataques que sufren este tipo de redes: - Ataques al protocolo WEB. Fuerca bruta. - Ataque Inductivo Arbaugh - Asociados a debilidades en el algoritmo key Scheduling de RC4 - Descubrimientode ESSID ocultos - Denegación de servicio - Ataues del tipo "Man in the middle" - Romper filtrado basado en direcciones - Envenenamiento de la cache ARP. Surgen herramientas para, por ejemplo, olfatear el "aire" con AirSnort, un sniffer para redes wireless y que aprovecha, junto a otras herramientas las debilidades del sistema WEP: http://www.virusprot.com/Nt240821.html Podemos también auditar redes wireless com NetStumbler desde un sistema W32: NetStumbler ó escanear con Wireless Scanner: Wireless Scanner También podemos dotar a nuestro sistema o red wireless de un IDS o sistema de detección de intrusos con AirDefense IDS. Y que mejor que un manual práctico, aunque sea en inglés, sobre la seguridad en este tipo de redes: "Security Practicum: Essential Home Wireless Security Practices": http://arstechnica.com/paedia/w/wireless-security-howto/home-802.11b-1.html Los famosos símbolos para indicar los accesos a redes wireless: Para estar al tanto de la tecnología sin cables: http://www.sincables.net/ Enlaces sobre WEP: Vulnerabilidad WEP. http://www-ma2.upc.es/~cripto/Q1-02-03/wep.pdf Seguridad ( o inseguridad) del algoritmo WEP. http://www.redlibre.net/wiki/moin.cgi/Vulnerabilidad_20WEP Sobre WEP. http://www.isaac.cs.berkeley.edu/isaac/wep-faq.html WEP. Configuración de la seguridad: Guía del usuario del adaptador Mini PCI para red local Intel(R) PRO/Wireless 7100 y 2100 3A http://support.jp.dell.com/docs/network/p51814/sp/wepsetup.htm Algunos consejos. - Deshabilitar el SSID broadcast. El SSID es el nombre de nuestra red. Si no conocieramos ni el SSID ni la claves wep, nos sería muy dificil entrar en esa red wireless. Muchos aparatos tienen activado por defecto, que publiquen ese nombre de red en todas las conexiones. - Filtrado por direcciones MAC. Aqui lo que hacemos es permitir que solo las tarjetas inalambricas que queramos puedan acceder, aunque siempre se puede piratear una dirección MAC. - Activar las claves de cifrado WEP y cambiarlas con regularidad, a costa de perder velocidad en la transmisión de datos. - Protejer las unidades y carpetas con contraseñas. - Implemente un sistema de red privada virtual (VPN) para aumentar la seguridad. La mayoría de los sistemas operativos incluyen un cliente VPN. Sobre WPA y TKIP. Para mejorar la criptografía de los datos, WPA utiliza su Temporal Key Integrity Protocol (TKIP), que, encaminando todas las conocidas debilidades del WEP, proporciona respuestas a las mismas con: • Una función de per-packet key mixing • Un control sobre la integridad del mensaje • Un “Initialization Vector” ampliado con reglas de secuencia • Un mecanismo de re-keying Pero que es eso de TKIP. La WECA (una alianza entre las mas importantes empresas que fabrican productos informáticos, que se encarga de certificar que el producto final sea 100% compatible con el estandar) (http://www.wi-fi.org/) está trabajando con una nuevo sistema de encriptación, la encriptación TKIP (Temporal Key Integrity Protocol). Básicamente las mejoras de esta encriptación es que tiene una gestión dinámica de las claves de cifrado, asignando a cada conexión una clave de cifrado diferente (ya no es estática) y además de eso, encriptación de cada paquete que se envie. La ventaja del TKIP es que es 100% compatible ocn el hardware actual a diferencia del EAP Detectando Sniffers en nuestra red. Redes conmutadas y no conmutadas. Vamos a tratar aquí, principalmente, la detección de sniffers en nuestra red desde el escenario más básico posible. Este escenarío sería una subred o red no conmutada. Aunque más adelante nos introduciremos brévemente en la escuha en redes conmutadas o basadas en switches y herramientas de detección en este tipo de redes. Antes que nada, decir que los sniffers no son fáciles de detectar y combatir, ya que se trata de programas que trabajan en modo pasivo. Las técnicas que se tratan aquí, por tanto, no son totalmente fiables, aunque en algunos casos si suponen una grn aproximación al descubrimiento de este tipo de software. Antes que nada y para enteder algunos coneceptos de este artículo veremos como funciona, brevemente, el protocolo ARP. Que es. Para que sirve ARP ? En una red Ethernet cuando queremos enviar un paquete IP entre dos hosts conectados las únicas direcciones válidas son las MAC y lo que circula son tramas Ethernet. Entonces y volviendo al ejemplo de antes cuando queremos enviar un paquete IP lo que se hace es meter el paquete dentro de una trama Ethernet y enviar. Formato de una cabecera ARP: HLEN Longitud dirección hardware PLEN Longitud dirección del protocolo OPERACION Código de operación (ARPreques ó ARPreply) SENDER HA Dirección de origen hardware SENDER IP Dirección de origen del protocolo TARGET HA Dirección de destino hardware Cual es el problema entonces ? El problema radica en que que sabemos la dirección IP del host de destino pero no su dirección MAC. Como se soluciona esto ? La solución está en que antes de enviar el paquete IP se debe usar ARP para averiguar cual es la dirección MAC del host destino de la conección que pretendemos realizar. Y como se hace ?. ARP tiene dos tipos básicos de mensajes: - mensaje de peticion o ARPrequest - mensaje de respuesta o ARPreply los dos viajan por nuestra red dentro de tramas Ethernet. Cuando queremos enviar un paquete IP desde un host origen (A) hacia un host destino (B) sucede: (A) crea un mensaje o petición ARPrequest indicando: - su dirección IP - su dirección MAC - dirección IP del host (B) - campo de dirección MAC host (B) sin rellenar. envia el ARPrequest a la dirección broadcast (todos los hosts de la red) pero sólo contesta uno de ellos (B). Entonces: (B) crea un mensaje ARPreply: - rellena el campo de dirección MAC con su MAC - intercambia las direcciones origen y destino - cambia el tipo de mensaje de ARPreques a ARPreply - envia el mesnaje ARPrpely a (A). Ya hay entonces información suficiente para establecer cualquier comunicación entre (A) y (B). Esto lo podemos comprobar utilizando un sniffer de red como Ethereal y filtrando por protocolos, en este caso ARP: C:scan>windump -qtn arp windump: listening on DeviceNPF_{604C8AE3-5FAC-45A5-BFAA-81175A8C32BF} arp who-has 192.168.5.241 tell 192.168.5.240 arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.5.4 tell 192.168.5.240 arp who-has 192.168.5.6 tell 192.168.5.240 arp who-has 192.168.5.44 tell 192.168.5.240 arp who-has 192.168.5.14 tell 192.168.5.240 arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.4.15 tell 192.168.4.10 arp reply 192.168.4.15 is-at 0:1:2:e7:57:cf arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.4.15 tell 192.168.4.1 arp reply 192.168.4.15 is-at 0:1:2:e7:57:cf arp who-has 192.168.4.234 tell 192.168.4.1 arp who-has 192.168.4.15 tell 192.168.4.13 arp reply 192.168.4.15 is-at 0:1:2:e7:57:cf..... Toda la información de las relaciones IP/MAC se guarda en la cache ARP. En un sistema Windows: C:>arp -a Interfaz: 192.168.4.3 on Interface 0x1000003 Dirección IP Dirección física Tipo 192.168.4.1 00-04-76-97-b3-a9 dinámico 192.168.4.20 00-a0-24-4e-4e-4e dinámico Sistemas Linux: $ arp -a serprint (192.168.4.2) at 52:54:05:fd:de:e5 infografia3 (192.168.4.3) at 00:90:27:6a:58:74 Una vez visto como funciona el protocolo ARP, seguimos con la detección de los sniffers. Detección en sistemas UNIX/Linux En entornos Linux o UNIX la verificación de una interface en modo promiscuo se puede hacer usando ifconfig. Este programa configura la interface de red instalada en un determinado host y obtiene información de la configuración en el momento de ejecutar el programa. Cuando un adaptador de red se encuentra en modo promiscuo, ifconfig nos devuelve la siguiente información: $ ifconfig -a eth0 Link Encap: 10Mbps Ethernet HWaddr: xx:xx:xx:xx:xx:xx inet addr: a.b.c.d Bcast: a.b.c.f Mask: m.m.m.m UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1 (OJO: Modo promiscuo) RX packets: 0 errors:0 dropped:0 overruns:0TX packets:0 errors:0 dropped:0 overruns:0 Interrupt:15 Base Address:0x300 Este sistema no es infalible. Existen programas que pueden hacer esta labor como: cpm (Check Promiscuous Mode) Este pequeño programa realizado por la Universidad de Carnegie Mellon, chequea el interfaz de red de la máquina descubriendo si está siendo utilizado en modo promiscuo (escuchando todo el tráfico de la red). $ cpm 4 network interfaces found: eth0:5: Normal eth0:3: Normal eth0:2: Normal eth0:1: Normal eth0: *** IN PROMISCUOUS MODE *** Existen otros programas como Antisniff, Sentinel, SniffDet, ifstatus o NEPED: Veamos como trabaja NEPED Tenemos que introducir la interface de red: $ neped eth0 ---------------------------------------------------------- > My HW Addr: 00:50:BF:1C:41:59 > My IP Addr: 192.168.0.1 > My NETMASK: 255.255.255.0 > My BROADCAST: 192.168.1.255 ---------------------------------------------------------- Scanning .... * Host 192.168.0.3, 00:C2:0F:64:05: FF **** Promiscuous mode detected !!! End. NEPED utiliza la técnica de realizar una simple petición ARP para cada una de las IPs de la red a diagnosticar, pero ojo, los paquetes no van destinados a broadcast (FF: FF: FF: FF: FF: FF), sino a una dirección aleatoria e inexistente. Sólo las interfaces en modo promiscuo verán estos paquetes, y de esta manera, sólo estas interfaces contestarán a estas peticiones. Existe también un dispositivo de hardware llamado Tap. Este dispositivo permite conectarse a un Hub o incluso a un switch de red al cual conectásemos un dispositivo (ordenador) para monitorizar la red. Existen tipos de Taps para cada tipo de red Ethernet 10 Mbps, 100 Mbps y 1 Gbps. Más información en: www.netoptics.com SniffDet - Remote Sniffer Detection http://prdownloads.sourceforge.net/sniffdet/sniffdet-0.9.tar.gz Usa lás técnicas test ICMP, test ARP, test DNS y test de ping de latencia. # ./sniffdet 0.9 A Remote sniffer Detection Tool Copyright (c) 2003 Ademar de Souza Reis Jr. Milton Soares Filho Usage: ./sniffdet [options] TARGET Where: TARGET is a canonical hostname or a dotted decimal IPv4 address -i --iface=DEVICE Use network DEVICE interface for tests -c --configfile=FILE Use FILE as configuration file -l --log=FILE Use FILE for tests log -f --targetsfile=FILE Use FILE for tests target --pluginsdir=DIR Search for plugins in DIR -p --plugin=FILE Use FILE plugin -u --uid=UID Run program with UID (after dropping root) -g --gid=GID Run program with GID (after dropping root) -t --test=[testname] Perform specific test Where [testname] is a list composed by: dns DNS test arp ARP response test icmp ICMP ping response test latency ICMP ping latency test -v --verbose Run in verbose mode -h, --help Show this help screen and exit --version Show version info and exit Defaults: Interface: "eth0" Log file: "sniffdet.log" Config file: "/etc/sniffdet.conf" Plugins Directory: "/usr/lib/sniffdet/plugins" Plugin: "stdout.so" You have to inform at least one test to perform vemos un ejemplo resultado de este software: ------------------------------------------------------------ Sniffdet Report Generated on: xxxxxxxxx 2003 ------------------------------------------------------------ Tests Results for target 192.168.2.1 ------------------------------------------------------------ Test: ARP Test Check if target replies a bogus ARP request (with wrong MAC) Validation: OK Started on: xxxx Finished on: Mxxxxx Bytes Sent: 84 Bytes Received: 60 Packets Sent: 2 Packets Received: 1 ------------------------------------------------------------ RESULT: POSITIVE ------------------------------------------------------------ ------------------------------------------------------------ Number of tests with positive result: #1 ------------------------------------------------------------ AntiSniff_v1.3 http://www.l0pht.com/antisniff Esta herramienta, tanto para plataformas linux/Unix como para Win32, es muy sencilla de usar y tan sólo es necesario inroducir el rango ede IPs a monitorizar en busca del posible sniffer. Usa las técnicas de ping de latencia, test DNS y test ARP. Sentinel http://www.packetfactory.net/Projects/sentinel/ Utiliza los métodos de: test DNS, test ARP, prueba ICMP Etherping, y ping de latencia. Uso de sentinel: ./sentinel [método] [-t <destino ip>] Métodos: [ -a test ARP ] [ -d test DND ] [ -i ICMP Test ping de latencia] [ -e ICMP test Etherpingt ] Opciones: [ -f <fichero> fichero o IP] [ -c <x.x.x> clase C a monitorizar] [ -n <úmero de paquetes a enviar> ] [ -I <dispositivo> ] Ejemplos: ./sentinel -a -t 192.168.1.2 Optimizado para usar el test ARP host 192.168.1.2 ./sentinel -d -f 1.1.1.1 -t 192.168.1.2 Optimizado para usar el test DNS host 192.168.1.2 ./sentinel -aed -c 10.2.2 Optimizado para escanear una red de clase c (10.2.2) usando el test ARP, DNS y test Etherping Optimizado para usar el test DNS host 192.168.1.2 Otras formas de detectar posibles sniffers * Detectar y controlar los logs que suelen generar los sniffers. * Detectar y controlar las conexiones al exterior. * Monitorizados los programas que acceden al dispositivo de red. * Normalmente una interface en modo promiscuo, queda reflejada en el fichero de logs: * $ cat /var/log/messages Otras técnicas de detección Sólo por nombrar algunas, son usadas por los programas anti-sniffers. Comentaremos la última: * Ping de latencia * Test ARP * Uso de un IDS. Por ejemplo Snort que contiene un preprocesador (arpspoof) que nos puede servir. Aquí las líneas de snort.conf configurando el preprocesador: # arpspoof #---------------------------------------- # Experimental ARP detection code from Jeff Nathan, detects ARP attacks, # unicast ARP requests, and specific ARP mapping monitoring. To make use # of this preprocessor you must specify the IP and hardware address of hosts on # the same layer 2 segment as you. Specify one host IP MAC combo per line. # Also takes a "-unicast" option to turn on unicast ARP request detection. # Arpspoof uses Generator ID 112 and uses the following SIDS for that GID: # SID Event description # ----- ------------------- # 1 Unicast ARP request # 2 Etherframe ARP mismatch (src) # 3 Etherframe ARP mismatch (dst) # 4 ARP cache overwrite attack preprocessor arpspoof preprocessor arpspoof_detect_host: 192.168.2.1 f0:0f:00:f0:0f:00 Otro IDS para sistemas Linux como Prelude Hybrid IDS (http://www.preludeids.org/rubrique.php3?id_rubrique=13), poseee un plugin ( ArpSpoof Plugin ) que nos ayuda a detectar incoherencias en mensajes ARP, conflicos con una base de datos ARPwatch (veremos esto más adelante), etc: Configuración de plugin: /usr/local/etc/prelude-nids/prelude-nids.conf ... [ArpSpoof] # # Search anomaly in ARP request. # # The "directed" option will result in a warn each time an ARP # request is sent to an address other than the broadcast address. # # directed; # arpwatch=<ip> <macaddr>; ... * Test DNS Las técnicas de detección. Breve explicación. El test DNS En este método, la herramienta de detección en sí misma está en modo promíscuo. Creamos numerosas conexiones TCP falsas en nuestro segmento de red, esperando un sniffer pobremente escrito para atrapar estas conexiones y resolver la direción IP de los inexistentes hosts. Algunos sniffers realizan búsquedas inversas DNS en los paquetes uqe capturan. Cuando se realiza una búsqueda inversa DNS, un utilidad de deteción de sniffers "huele" la petición de las operaciones de búsqueda para ver si el objetivo es aquel que realiza la petición del host inexistente. El Test del Ping Este método confia en un problema en el núcleo de la máquina receptora. Podemos construir una petición tipo "ICMP echo" con la dirección IP de la máquina sospechosa de hospedar un sniffer, pero con una dirección MAC deliberadamente errónea. Enviamos un un pacquete "ICMP echo" al objetivo con la dirección IP correcta, pero con una dirección de hardware de destino distinta. La mayoría de los sistemas desatenderán este paquete ya que su dirección MAC es incorrecta. Pero en algunos sistemas Linux, NetBSD y NT, puesto que el NIC está en modo promíscuo, el sniffer asirá este paquete de la red como paquete legítimo y responderá por consiguiente. Si el blanco en cuestión responde a nuestra petición, sabremos que está en modo promíscuo. Un atacante avanzado puede poner al día sus sniffers para filtrar tales paquetes para que parezca que el NIC no hubiera estado en modo promíscuo. El Test ICMP Ping de Latencia. En éste método, hacemos ping al blanco y anotamos el Round Trip Time (RTT, retardo de ida y vuelta o tiempo de latencia) Creamos centenares de falsas conexiones TCP en nuestro segmento de red en un período de tiempo muy corto. Esperamos que el sniffer esté procesando estos paquetes a razón de que el tiempo de latencia incremente. Entonces hacemos ping otra vez, y comparamos el RTT esta vez con el de la primera vez. Despues de una serie de tests y medias, podemos concluir o no si un sniffer está realmente funcionando en el objetivo o no. El test ARP Podemos enviar una petición ARP a nuestro objetivo con toda la información rápida excepto con una dirección hardware de destino errónea. Una máquina que no esté en modo promíscuo nunca verá este paquete, puesto que no era destinado a ellos, por lo tanto no contestará. Si una máquina está en modo promiscuo, la petición ARP sería considerada y el núcleo la procesaría y contestaría. Por la máquina que contesta, la sabemos estamos en modo promiscuo. El test Etherping Enviamos un "ping echo" al host a testear con una IP de destivo correcta y dirección MAC falseada. Si el host responde, es que su interfaz está en modo promiscuo, es decir, existe un sniffer a la escucha y activo. Protegerse contra la acción de los sniffers A grandes rasgos para protegernos de los sniffers y para que éstos no cumplan sus objetivos de olfateo de contraseñas y en general nos "lean datos sensibles" en texto plano -sin cifrado fuerte-, podemos hacer uso de diversas técnicas o utilizar sistemas como: * Redes conmutadas (no siempre es efectivo) * PGP * SSL * SSH * VPN, * etc. Aunque ya veremos más adelante que ni siquiera el uso de SSH, por citar un ejemplo, nos puede protejer efectivamente del uso de ciertos tipos de sniffer como ettercap. Detección en sistemas Windows PromiScan "PromiScan (www.securityfriday.com) es una utilidad de distribución gratuita diseñada para dar caza a los nodos promiscuos en una LAN rápidamente y sin crear una carga pesada en la red. Hay que tener en cuenta que localizar un nodo promiscuo es una tarea ardua, y que en muchos casos el resultado es incierto; no obstante, PromiScan consigue mostrar cada uno de esos nodos de una manera transparente, claramente visible. Para usar PromiScan es necesario contar con Windows 2000 Professional y haber instalado previamente el controlador WinPcap." http://www.securityfriday.com/ToolD...iscan_003.html. PromiscDetect C:scan>promiscdetect PromiscDetect 1.0 - (c) 2002, Arne Vidstrom ([email protected]) - http://ntsecurity.nu/toolbox/promiscdetect/ Adapter name: - NIC PCI 3Com EtherLink XL 10/100 PCI para administraci¾n completa del equipo (3C905C-TX) Active filter for the adapter: - Directed (capture packets directed to this computer) - Multicast (capture multicast packets for groups the computer is a member of) - Broadcast (capture broadcast packets) - Promiscuous (capture all packets on the network) WARNING: Since this adapter is in promiscuous mode there could be a sniffer running on this computer! http://www.ntsecurity.nu/cgi-bin/do...scdetect.exe.pl http://ntsecurity.nu/downloads/promiscdetect.exe ProDETECT 0.2 BETA http://sourceforge.net/projects/prodetect/ http://prdownloads.sourceforge.net/prodetect/proi386.exe?download Alerta de ProDETECT: Detección en redes conmutadas En redes commutas o que hagan uso de switches, la técnica de ARP poisoning o envenenamiento arp es la más efectiva. Esta técnica consiste, muy brevemente, en modificar (envenenar) la tabla ARP de los host involucrados en el ataque para que éstos envíen a la red tramas Ethernet con destino la MAC del atacante. Esto significa que el switch entregará los datos de las comunicación a dicho host. Para evitar el refresco de la caché ARP es necesario el envio constante de arp-reply. Una posible solución o defensa sería el uso de MACs estáticas, con el fin de que no puedan ser modificadas, aunque en algunos sistemas Windows esto no es eficiente al 100 por 100. En sistemas Linux la herramienta ARPWatch ( http://www-nrg.ee.lbl.gov/ ) nos puede servir para detectar el uso del envenenamiento ARP en nuestro sistema. Con ARPWatch podemos comprobar la correspondencia entre pares IP-MAC (Ethernet). En caso de que un cambio en un par se produzca (esto es, se escuche en el interfaz de red del sistema), ARPWatch envía un correo de notificación del suceso a la cuenta root o administrador del sistema con un mensaje tipo "FLIP FLOP o Change ethernet address". También podemos monitorizar la existencia de nuevos host ( aparición de una nueva MAC en la red). # ./arpwatch -? Version 2.1a11 usage: arpwatch [-dN] [-f datafile] [-i interface] [-n net[/width]] [-r file] [-u username] [-e username] [-s username] # cat /etc/sysconfig/arpwatch # -u <username> : defines with what user id arpwatch should run # -e <email> : the <email> where to send the reports # -s <from> : the <from>-address OPTIONS="" Una herramienta similar a ARPwatch pero para sistemas Windows la encontramos en WinARP Watch v1.0 (http://www.securityfocus.com/data/tools/warpwatch.zip). Esta herramienta no enviará correo alguno a ningún administrador, pero nos tendrá puntualmente informados sobre la caché ARP, las correspondencias IP/MAC, cualquier nuevo par que se añada a la caché, etc. Una alerta de WinARP Watch: Existe en el mercado un tipo especial de switches que está preparados para que la tabla ARP no pueda ser modificada. Hablando de herramientas, una que realiza este trabajo de escucha en redes conmutadas con gran eficacia es ettercap. Ettercap ( http://ettercap.sourceforge.net ) es capaz de escuchar tanto redes basadas en hubs como en switches. Además puede escuchar conexiones SSH e incluso detectar otros envenenamientos o modificaciones de la tabla ARP. Detección de envenenamiento ARP con ettercap en un sistema Windows. C:...ettercap>ettercap -Nc ettercap 0.6.b (c) 2002 ALoR & NaGA List of available devices :[/i] --> [dev0] - [3Com EtherLink PCI] Please select one of the above, which one ? [0]: Your IP: 192.168.4.3 with MAC: 00:04:76: F2:C9:5F on Iface: dev0 Building host list for netmask 255.255.255.0, please wait... Sending 255 ARP request... * |==================================================>| 100.00 % Resolving 14 hostnames... * |==================================================>| 100.00 % Checking for poisoners... MAC of 192.168.4.59 and 192.168.4.235 are identical ! Otra herramienta que detecta cambios en los pares IP/MAC así como ataques tipo arp-spoofinges ACiD (ARP Change intrusion Detection) : C:scanACID>acid ACiD - 0.0.2 - (c) 2002 Roberto Larcher - [email protected] All rights reserved. Press CTRL+C to stop. Initializing default adapter. Please wait... IP: 0.4.168.192 Subnet Mask: 0.255.255.255 Network type: Ethernet ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.2.3 00:a0:24:4d:bc:69 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.2.3 00:a0:24:4d:bc:69 ACiD: bogon 192.168.2.3 00:a0:24:4d:bc:69 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.20 00:a0:24:4e:4e:4e ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.15 00:01:02:e7:57:cf ACiD: bogon 192.168.4.10 00:a0:24:4e:51:6b ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.4.3 00:04:76:f2:c9:5f ACiD: bogon 192.168.4.3 00:04:76:f2:c9:5f ACiD: bogon 192.168.4.20 00:a0:24:4e:4e:4e ACiD: bogon 192.168.5.240 00:06:5b:05:9a:e7 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.4.20 00:a0:24:4e:4e:4e ACiD: bogon 192.168.4.15 00:01:02:e7:57:cf ACiD: bogon 192.168.4.8 00:10:4b:4d:15:bb Ctrl+C detected... IP <-> MAC table: 192.168.2.3 00:a0:24:4d:bc:69 192.168.4.1 00:04:76:97:b3:a9 192.168.4.10 00:a0:24:4e:51:6b 192.168.4.15 00:01:02:e7:57:cf 192.168.4.20 00:a0:24:4e:4e:4e 192.168.4.3 00:04:76:f2:c9:5f 192.168.4.5 00:04:76:9a:66:a6 192.168.4.8 00:10:4b:4d:15:bb 192.168.5.240 00:06:5b:05:9a:e7 ArpCount table: 192.168.2.3 -3 192.168.4.1 -8 192.168.4.10 1 192.168.4.15 -2 192.168.4.20 3 192.168.4.3 -2 192.168.4.5 -10 192.168.4.8 1 192.168.5.240 -6 En la consola de ACID si existe un error en la paridad IP/MAC nos alertará de esta manera: ACiD: bogon 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: ethernet mismatch 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: bogon 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: ethernet mismatch 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: bogon 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: ethernet mismatch 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: bogon 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: ethernet mismatch 192.168.4.5 00:04:76:f2:c9:5f (00:11:22:33:44:55) ACiD: bogon 192.168.4.1 00:04:76:97:b3:a9 ACiD: bogon 192.168.4.5 00:04:76:9a:66:a6 Possible spoof 192.168.4.5 00:04:76:9a:66:a6 was at 00:04:76:f2:c9:5f - . - Se agradecen los comentarios =D

Hace algún tiempo publique algunos posts sobre como iniciarse en el amplio y maravilloso mundo de la programación . En esa ocasión recalque el hecho de que hubo algunos puntos que se me escaparon o que quería profundizar de mejor manera, por lo que probablemente haría un nuevo post en el futuro (muy lejano ). Bueno, el momento ha llegado, aunque no precisamente continuando el mismo post, si no que algo relacionado. Hoy les traigo un post enfocado puramente a código, compuesta de consejos y buenas prácticas que nunca están demás, especialmente en estos momentos que casi todo lo que vemos en la Web, ya sea Taringa!, Facebook u otra red social en la que estemos involucrados, aunque sea en una pequeña parte, es programación. Al no haber herramientas necesarias (a excepción quizás de un editor Web), vamos de lleno al contenido: El siguiente post está compuesto de un conjunto de consejos y buenas prácticas a la hora de programar. A pesar de que está orientado a Web, algunos puntos son aplicables a otro tipo de lenguajes en los que se puede utilizar de la misma manera cambiando algunas variables. 1.- Reutilización de variables En la programación, las variables en las que almacenamos datos tienen lo que llamamos un “ciclo de vida”: Desde su nacimiento (el momento en el que las declaramos) hasta su muerte (última línea en que han sido utilizadas), toman distintos valores y forman parte de una serie de procesos que nos llevan a obtener resultados. Posterior a su último uso, estas variables permanecen sin prestar utilidad. A pesar de que muchos lenguajes tienen implementada una característica conocida como recolector de basura, el cual se encarga de desocupar o limpiar todas las áreas de memoria que se encuentran utilizadas pero inactivas, en muchas ocasiones esto no ocurre o existe un periodo durante la ejecución de un programa en que seguimos creando variables y vamos ocupando más y más áreas de memoria, lo que adicionalmente nos puede llevar a confusión con el nombre de las mismas. Es por esto que es recomendable, si vemos que hemos dejado de utilizar una variable en particular, reutilizarla, siempre y cuando no afecte el código donde las usamos originalmente. Por ejemplo, en vez de usar esto: i=0; while(i<10) { echo 'Hola mundo'; i++; } j=0; while(j<10) { echo 'Adios!'; j++; } Podemos utilizar esto, obteniendo el mismo resultado de manera más óptima: i=0; while(i<10) { echo 'Hola mundo'; i++; } while(i>0) { echo 'Adios!'; i--; } No solo reutilizamos la misma variable para ejecutar ambas tareas, sino que a su vez optimizamos el código, mejorando la ejecución final. Claramente es un ejemplo bastante básico, pero me sirve para ilustrar el punto. A medida que nuestras aplicaciones van creciendo, necesitamos manipular una mayor cantidad de variables, por lo que puede volverse algo confuso de manejar. La reutilización nos sirve para tener un mejor control de lo que tenemos y al mismo tiempo nos permite hacer nuestro código mucho más simple. 2.- Nombrar como corresponde Escribir código es de cierta forma contar una historia. Desde la declaración o nacimiento de las variables, hasta lo que hace cada una de ellas hasta el final, tenemos actos claros y definidos que permiten a cualquiera con conocimientos de programación poder seguir la historia del principio hasta el término. Y como tal, es importante tener consistencia en lo que escribimos, con respecto al nombre que le damos a las variables y funciones que utilizamos. En lo anterior resalté un hecho muy importante: Todo el código que escribamos será revisado por alguien. Ya sea otros programadores o bien nosotros mismos más adelante cuando queramos optimizar o reutilizar, siempre habrá alguien que deba hacer la traza del código y ver que hace cada cosa. Es por esto que es importante que mantengamos concordancia con respecto a los nombres y seguir una lógica que nos permita mantener un orden y claridad a futuro. Por ejemplo, si recibimos los datos de un usuario a través de un formulario, es bueno que las variables a las que asignemos valores tengan un prefijo definido (por ejemplo usuario). De esta forma, cuando nos encontremos 30 líneas más abajo y necesitemos recurrir a ellas, ya sabremos bajo que estructura trabajamos y minimizaremos el margen de error. Existen 2 convenciones definidas para nombrar elementos a la hora de programar, que si bien no es obligación usarlas, si pueden servir en algunos casos: camelCase: En esta, la primera letra de cada palabra nueva lleva mayúscula, a excepción de la primera. Ej: $usuarioClave o function devuelveDatos. underscore: En la cual cada palabra es separada por un underscore o guión bajo. Ej: $usuario_clave o function devuelve_datos. Al programar somos libres de definir nuestras propias reglas para nombrar. No obstante, si estamos realizando trabajo colaborativo con otros programadores, es bueno utilizar alguna de las convenciones aceptadas, con el fin de estandarizar el trabajo y hacer todo más entendible para los demas. Lo importante es definir una estructura y un estándar que nos permita hacer más uniforme nuestro código y de esta forma hacerlo mucho más entendible. 3.- Agrupar el código Si tomamos cualquier programa que hayamos escrito en el pasado, podremos apreciar que dentro de el, hay pequeñas secciones de código relacionadas entre sí por las funciones o tareas que realizan y que pueden o no tener directa relación con lo que viene líneas más abajo. Por un tema de orden, y para facilitar la documentación (punto que veremos más adelante) es bueno ir agrupando estas secciones y separarlas del resto del código con una línea en blanco. De esta forma, cada vez que necesitemos modificar una porción del programa será mucho más sencillo aislarlas y trabajar sobre ellas, ya que sabremos exactamente en donde empieza y donde termina esa parte del programa. Por ejemplo, en un programa donde recibimos datos a través de un formulario, los insertamos en una base de datos y desplegamos el resultado al visitante: $usuario_id = $_POST["usuario_id"]; $usuario_clave = $_POST["usuario_clave"]; $usuario_correo = $_POST["usuario_correo"]; $conexion = mysql_connect("localhost", "usuariobd", "clavebd"; mysql_select_db("mibd"; $consulta = "INSERT INTO usuarios VALUES('$usuario_id', '$usuario_clave', '$usuario_correo')"; $resultado = mysql_query($consulta); echo 'El usuario se ha creado satisfactoriamente'; En el código anterior podemos ver claramente que hace cada parte del programa: Primero recibimos los datos desde un formulario, luego hacemos la conexión y selección de base de datos, posterior a eso ejecutamos la consulta y finalmente mostramos el mensaje de éxito al usuario. Claro y limpio. Si al momento de ejecutar encontramos un error en una de las partes será mucho más sencillo volver a ella, ajustar y volver a probar. 4.- Indentar el código Probablemente los 2 errores más clásicos que obtenemos al programar son la ausencia del punto y coma ( ; ) al terminar una sentencia y la falta de una llave de apertura o cierre en una iteración. Sobre el primero no es mucho lo que se pueda hacer, más que fijarse, pero sobre el segundo una de las causas más comunes de la ocurrencia de este error es la falta de indentación del código, lo que muchas veces nos hace confundir una llave de otra iteración con la que estamos escribiendo actualmente, lo que puede llevar a 2 situaciones, o bien el código no se ejecuta bien, o la iteración se ejecuta como sub-sección de otra, lo que puede llevar a resultados aún peores. Adicional a lo anterior, y tal como he remarcado en casi todos los puntos anteriores: orden. Siempre, y repito, siempre deberemos releer el código en algún momento y si bien cuando lo escribamos sabremos perfectamente que hace cada parte, no será así al tiempo después, por lo que mientras más ordenado y estructurado lo mantengamos, más sencillo será volver a trabajar sobre el. Así que recapitulando, esto no es correcto: while(i<10) { if(x == 'Letra equis') { echo 'Es la letra equis!'; } else { echo 'No es la letra equis!'; } } Esto si es correcto: while(i<10) { if(x == 'Letra equis') { echo 'Es la letra equis!'; } else { echo 'No es la letra equis!'; } } De esta forma, a primera vista ya sabemos que el if y el else se ejecutarán dentro del while y cada vez que se repita la iteración, queda todo más ordenado y hasta estéticamente se ve mejor. 5.- No repetir, no hagas los que hacen con Call Of Duty. Este es un error bastante común que todos cometemos, especialmente cuando empezamos a programar y de forma inconsciente. Es natural que dentro de nuestros programas escribamos una, y otra, y otra vez el mismo código, o que bien en distintos programas de una misma aplicación (por ej. en distintas páginas PHP que forman parte de un mismo sistema) repitamos el mismo proceso o tengamos líneas repetidas. La gracia de la programación es justamente evitar eso y nos entrega una serie de herramientas a tener en consideración. Tal como utilizamos ciclos para ejecutar una misma tarea varias veces, siempre es posible parametrizar un proceso. Solo bastante notar que es lo que estamos repitiendo, descubrir o definir el algoritmo, buscar los parámetros y formar una función a la que podamos llamar que haga la tarea independiente de los valores entregados. Por otro lado, ¿tenemos un pié de página que se repite en cada página del sitio?, ¿un menú fijo que aparece en cada sección?. Hagamos uso de los includes y requires que PHP nos entrega, definamos funciones y plantillas que podamos reutilizar una y otra vez sin problemas. Una de las mayores bellezas de la programación es justamente esa: reutilizar. Podemos adaptar un mismo trozo de código para múltiples situaciones, haciendo la ejecución mucho más rápida y armónica. 6.- Orden en sentencias SQL Esta es una costumbre personal que adopté cuando empecé a hacer mis primeras armas en programación Web, por lo que fue una agradable sorpresa ver que estaba considerado como una buena práctica, y por eso hoy la remarco acá. Las sentencias SQL pueden llegar a ser largas, y por ende complejas de leer, especialmente si están insertas en una maraña de código PHP y/o HTML, por lo que debemos hacer lo posible para mantener un orden dentro de ellas y así hacerlas más fáciles de revisar en caso de errores. ¿A qué nos referimos con esto?, en particular a un punto: Poner en mayúscula las palabras reservadas de SQL. Esto nos permitirá siempre saber a primera vista que es lo que se hace y no nos llevará a confusión en caso de que alguna tabla o variable con la que estemos trabajando tenga un nombre similar a ellas. Por ejemplo: SELECT auto_patente, auto_marca, auto_color, auto_id_propietario, propietario_nombre, propietario_telefono FROM auto a, propietario p WHERE auto_id_propietario = propietario_rut ORDER BY auto_patente DESC Es mucho más sencilla de leer que: select auto_patente, auto_marca, auto_color, auto_id_propietario, propietario_nombre, propietario_telefono from auto a, propietario p where auto_id_propietario = propietario_rut order by auto_patente desc Cuando estemos revisando código en texto plano a las 3 AM buscando el fatídico error agradecerán destacar las palabras reservadas, las cuales si se fijan, establecen una separación entre las distintas partes de la consulta. 7.- No reinventar la rueda Famosa frase que más de alguno ha escuchado anteriormente. Al programar, muchas veces tenemos la mala costumbre de querer hacer todo y confundimos la propiedad sobre una aplicación con generar el 100% del código. Nada más alejado de la realidad. Una de las gracias de esta gran red llamada Internet (¿Inter.. net?, I´ll be your guide) es la cantidad de recursos que tenemos a nuestra disponibilidad, desde clases a trozos de código, es muy probable que muchas de las funcionalidades que necesitamos implementar ya hayan sido desarrolladas y puestas a disposición para utilizarlas, así que ¿por qué no aprovecharlas?. No tiene nada de malo, y en realidad es muy ventajoso. No perdamos tiempo reinventado la rueda, y mejor veamos que podemos construir a partir de ella. No hay que tener dudas sobre incorporar librerías externas a nuestros desarrollos, siempre que respetemos cualquier licencia bajo las que hayan sido liberadas obviamente. Esto nos permitirá ahorrar un tiempo considerable que podemos dedicar a mejorar otras partes más críticas de la aplicación y mejorar los tiempos totales del desarrollo, que es algo que siempre debemos vigilar. Lo más importante de recordar es que ser un buen programador no significa hacer todo desde cero, si no que tener la habilidad de identificar que integraciones podemos hacer con herramientas existentes y optimizar así el tiempo total de trabajo. 8.- Codificar genéricamente Un par de puntos más atrás hablaba justamente de no repetir código. Este punto va precisamente de la mano. En muchos desarrollos en los que trabajemos a través del tiempo, veremos que es necesario desarrollar funcionalidades similares a las que hemos trabajado en el pasado, por lo que un buen consejo es hacer desarrollos genéricos con el fin de poder reutilizarlos y ahorrar tiempo. Por ejemplo, si inicialmente hacemos un sistema que incluya un registro de usuarios y en otro sistema necesitamos de lo mismo, ¿por qué no desarrollar una función genérica que reciba los parámetros necesarios para crear el usuario y así reutilizar bajo distintas situaciones?. De tal forma son muchos los casos en los que podremos ver que es posible reutilizar código de desarrollos anteriores, así que ahorremos tiempo y preparemos código estándar para utilizar. 9.- Revisar código de otros programadores Hace algún tiempo tuve la fortuna de trabajar como ayudante en un curso de programación gráfica en la Universidad, lo que me dio la oportunidad de revisar código de otros desarrolladores todas las semanas, una experiencia a la que todos deberían someterse en algún momento. Todos pensamos de forma distinta, y como tal, todos encontramos distintas soluciones o distintas formas de ejecutar una solución en particular, por lo que siempre es bueno revisar código de otros programadores, ya sea en librerías que descargamos o en sistemas que tengamos la posibilidad de ver. Eso nos ampliará la visión que tenemos sobre un lenguaje en particular y muchas veces nos permitirá ver formas más óptimas que las nuestras de codificar, lo que podremos incorporar a futuro. De la mano con lo anterior, siempre es una buena práctica plantearse nuevos desafíos al momento de hacer un desarrollo comparado con lo que hemos hecho anteriormente, y revisando código de otros programadores es una buena forma de planteárselos. 10.- Documentar como un campeón Uno de los puntos más importantes, sino el más importante, de este post. No podemos enfatizar lo suficiente la importancia de documentar el código y sobretodo de hacerlo correctamente. Si hay un punto en común de casi todo lo que vimos hoy, es el de facilitar la revisión del código, ya sea para otros desarrolladores o para nosotros mismos a futuro, y la documentación es fundamental en aquella tarea. Comentar que hace cada función, que rol cumple una variable en especial o porque hicimos algo de cierta manera será clave cuando los recuerdos no sean tan frescos en el futuro y necesitemos hacer modificaciones sobre el código. Adicionalmente a lo anterior, no es bueno exagerar. Si bien mientras más documentado esté el código será mejor, es bueno evitar comentarios obvios. Por ejemplo, si tenemos un ciclo que lo único que hace es mostrar el valor de una variable, no es necesario comentarlo, ya que a primera vista se puede ver sin problemas lo que hace. Así que en resumen es eso, comentar, pero ser criterioso a la hora de hacerlo. A final de cuentas es por nuestro propio bien, así que estimemos de forma correcta cuando y como hacerlo. Y con eso termino este sencillo (y extenso) post sobre como, ustedes, taringueros programadores, pueden optimizar sus codigos en solo 10 sencillos pasos, la que espero que sea de utilidad para todos aquellos dedicados a la programación o que buscan aprender más al respecto. Como siempre, les recuerdo que este post ha sido creado por: @ienrikex Cualquier duda o comentario que puedan tener, por favor, mandarme un MP o comentar en las lineas a continuación Muchas gracias por leer y será hasta un próximo post.
"El 14 de abril hubo 535 máquinas dañadas, eso representa un universo de votos afectados. En 286 centros de votación hubo testigos de oposición retirados, incluso algunos a punta de pistola, y estos centros representan 722.983 votos. Cuando no hay testigos, significa que puede haber votos asistidos y personas que votan más de una vez. Hay alrededor de 600.000 personas que ya murieron en el registro electoral. Hay 1176 centros donde el candidato Maduro sacó más votos que el presidente Chávez, hay un centro en Yaracuy donde sacó casi 1000% más votos ¿Quién puede creer que en algún centro de votación Maduro pudo sacar más votos que el presidente Chávez, si más bien en el resultado final votaron menos personas por el oficialismo?", explicó. El candidato presidencial de la oposición, Henrique Capriles Radonski, aseveró éste martes que tomó la decisión de suspender la manifestación convocada para este miércoles al Consejo Nacional Electoral en Caracas. “Vamos a derrotar esto con la protesta pacífica, ser pacífico no es ser débil. El que grita más duro no es más inteligente. El Gobierno quiere otro 11 de abril, pero aquí no habrá ni 11 de abril ni 27 de febrero”, precisó. Indicó que el objetivo de su exigencia es que exista una auditoria para contar voto a voto y adicionalmente se constate con los cuadernos y las actas de votación. "Yo no estoy pidiendo que se anuncie un ganador distinto, sólo estoy pidiendo que se permita contar voto a voto. Esto es garantía para el futuro y la democracia", aseveró. Capriles pidió que se calme un poquito a Maduro, quien más temprano advirtió a través de la cadena nacional de radio y televisión que estaba dispuesto a radicalizar esta revolución, para lo cual, aseguró, cuenta con el apoyo del pueblo y de la Fuerza Armada. PD: Yo vi la cadena, y ademas de toda esta información, también pidio que sustituyendo la movilizacion de mañana, se hicieran cacerolazos todos los dias a las 8 pm hasta el Viernes, cuando supuestamente proclamarian a Maduro como presidente. En este momento hay un fuerte cacerolazo, nunca vi nada similar, y creo que supera a el de ayer. PD2: Maduro también pidio despues que se oyera el himno nacional y las palabras de Chavez a todo volumen a las 8 pm, que casualidad.
En el momento en que el excandidato presidencial, Henrique Capriles, respondía a la cadena de radio y televisión donde se editaron sus declaraciones, se lanzó una nueva cadena, repitiendo justamente el mensaje que este criticaba. Inmediatamente se inició un cacerolazo en el este de Caracas, en repudio a la nueva cadena. El líder opositor se encontraba en una rueda de prensa con medios nacionales e internacionales, donde justamente empezó a criticar el contenido de esa mensaje en cadena nacional. Inmediatamente después que el Gobierno nacional repitiera la cadena que transmitió este martes al mediodía, interrumpiendo así una rueda de prensa que ofrecía el candidato de la Mesa de la Unidad, Henrique Capriles Radonski, se desató un cacerolazo en la ciudad capital. A través de la red social Twitter los seguidores de Capriles informaron que la protesta pacífica fue inmediata y que tuvo la misma fuerza que la pasada semana. @Naky aseguró ¡El cacerolazo en esta zona es superior a todos los que se produjeron antes! Estos necesitan generar violencia a cualquier costo. Por su parte Eduardo Battistini @ebattistini colocó: Duro contra la cadena abusiva! RT @JoxiAguilera: y se desató cacerolazo en el cigarral! Se informó que sonaron cacerolas en Bello Monte, Candelaria, Chaguaramos, Catia, Petare, Palo Verde, Cafetal, Terrazas del Club Hípico, como también en Valencia.
Hola Taringueros!.. Vengo con este post algo preocupado y molesto... En estos últimos años se ha venido dando una serie de programas y leyes en defensa de los derechos del niño y la mujer. Sin embargo, ¿eso nos asegura el bienestar?, ¿acaso estos programas y leyes bastarán para cesar los maltratos físicos y psicológicos que se producen día a día contra ellos?..... En este post veremos los casos mas sorprendentes de violencia familiar... Gracias por ver... 1er caso: Hombre colgó a su hijo de una viga porque se orinó en la cama Los gritos de la madre provocaron que los vecinos la ayudaran a detenerlo. Israel Bedoyrubina no encontró mejor castigo que golpear y atar a una soga a su hijo para luego colgarlo por haberse orinado en la cama. Según informó el Diario Ajá, el agricultor ató el cuello de su hijo con una soga y para luego colgarlo de una viga en su domicilio en Ate. El niño quedó con serias heridas en el cuello. Agripina Sánchez, madre del niño no pudo detenerlo pero sus gritos hicieron que los vecinos se acercaran a la casa y separaran al agresor de su hijo a empujones. ¡Que mal padre! ¿No creen? 2Do caso..(pienso que el mas triste de todos) Las escenas de violencia doméstica llegan a conocerse y a espantarnos cuando una tragedia las torna visibles. Generalmente, una mujer debe morir para que, por un breve lapso, la sociedad entera hable del tema. Algo así sucedió en Santa Fe en 1933. El asesinato de Ramona de Fernández en 1933 a manos de su marido y ante la mirada aterrada de sus pequeños hijos conmovió a Santa Fe. El diario que había sido fundado por don Salvador Espinosa tituló en aquel agosto: “A HACHAZOS una mujer fue brutalmente asesinada por su marido. Después el criminal se degolló con una navaja de afeitar. La mujer, con la cabeza destrozada, murió en el acto. No murió él, pero se halla hospitalizado en grave estado. ‘Me quería abandonar con los chicos, por eso la maté’”. Ramona y Santiago se habían casado hacía 12 años. Ella tenía 14, él 28. Siete hijos habían nacido del matrimonio, pero sólo dos habían sobrevivido. El relato del crimen lo realizó el propio Santiago Fernández, a partir de lo cual el diario Santa Fe reconstruyó los hechos. La crónica se inicia señalando que Fernández había descubierto que su esposa lo engañaba. Cuando la confrontó, ella “haciendo gala de impudor —dice Fernández— le dijo que ya estaba cansada de él y que tenía relaciones con otro”. “Ante la certidumbre de que mi mujer me engañaba, que me lo confesaba sin recelo y que iba a abandonarme con los chicos, resolví matarla, por mala y descorazonada”, confesó. Pero el diario descreía: “Es verdad lo que cuenta Fernández? O sólo quiere justificar en cierto modo su crimen y procura así atenuar su culpa?” El atroz crimen se desarrolló de la siguiente manera: Eran más o menos las 22 horas cuando sostuvieron la última conversación y poco después Ramona se quedaba dormida. (…) Fernández permanecía despierto maquinando su atroz venganza. A las 24 horas más o menos, se levantó. Los dos chicos dormían profundamente lo mismo que la madre en la misma pieza. De debajo de una mesa Fernández tomó el hacha leñera como de tres kilos de peso, y acercándose a la cama descargó sobre la cabeza de su mujer un terrible golpe. El filo penetró horizontalmente a los ojos llegando hasta las vértebras cervicales. La víctima del salvaje vengador dio un feroz grito, uno solo, pero de tal intensidad que despertó a uno de los chicos. Fue así como resultó testigo del drama. Los llantos de la criatura despertaron su hermano, que también vieron como entre sueños de pesadilla, cuando su padre seguía descargando golpe tras golpe sobre la cabeza de su mujer, hasta que el cuerpo ya no hizo ningún movimiento. Las ropas de la cama se tiñeron de rojo. Fernández, con el hacha ensangrentada en las manos, jadeante, parecía más trágico a la débil luz de la lámpara de petróleo. —Y vos, qué estás haciendo?—preguntóle ríspido a Alfredo que se había incorporado en la cama. — Tu madre no tiene nada, mañana estará sana. Dormite! —le ordenó. La criatura escondió su cara entre las cobijas y se puso a llorar. HORAS INFERNALES Realizada su obra Fernández salió de la casa y vagó varias horas. Llegó hasta un café situado cerca del Mercado de Abasto y —allí se puso a beber vino hasta las 4 horas de ayer aproximadamente en que regresó a su casa. Sus hijos dormían con esa inconciencia propia de la edad. Fernández contempló un buen rato el cadáver de su esposa, la cara horriblemente desfigurada por los golpes, como puede verse en la fotografía que publicamos. Luego, como impulsado por el remordimiento, pensó en eliminarse. Primero tuvo la intención de quemar la pieza para que murieran también con él los hijos y derramó sobre los muebles el contenido de una botella de kerosene. Pero se arrepintió y apoderándose de una navaja de afeitar mellada resueltamente se infirió un extenso tajo en la garganta. El poco filo de la navaja no permitió que la herida fuera muy profunda, y si bien es demás de diez centímetros de extensión, no es de mucha gravedad y posiblemente Fernández se salvará para ir a la cárcel a purgar su crimen. Fue uno de los niños el que se despertó ante las quejas de su padre herido. Eran las 6 de la mañana y a sus gritos, acudieron los vecinos y posteriormente los oficiales de policía de la comisaría 6ª. 3er Caso: Viendo hoy la televisión local veía un caso de violencia familiar bastante extraño (y extremista), un padre golpeó a su hijo de 10 años el día martes 24 de junio del presente año porque “se trabó” y no supo contestar la respuesta a una multiplicación que a su padre le parecía bastante simple. Estos hechos se suscitaron en la ciudad de Monterrey, aunque el padre agresor llamado Jesús Alvarado Rodríguez es originario del estado de Chiapas. “Se me pasó la mano, fue un momento de coraje nadamás” argumentaba el padre golpeador cuando fue entrevistado en el departamento de policía de la localidad. Lo peor del caso, cuando se le preguntó al agresor cuanto era 6 x 9 (54), el hombre contestaba con evasivas y nunca dió una respuesta concreta. El departamento de Justicia Familiar decidirá el castigo que recibirá este hombre. Los casos de violencia familiar en el estado han ido en aumento con el paso del tiempo, por lo que las autoridades decidieron hace poco reformar la ley para evitar que se conceda el “perdón” a miembros de la familia que comentan este tipo de delitos; a ver si da resultado, para mí sera igual, pues la mayoría de estos hechos se suscitan cuando los agresores se encuentran bajo la influencia del alcohol y/o drogas, por lo que no tienen control de sus actos, ni se van a andar acordando de las consecuencias, cegados por la ira. 4to caso: Un padre presuntamente golpea a su niño y se suicida; el infante de tres años está malamente herido en el hospital; y su madre está bajo investigación y en riesgo de perder la patria potestad de dos hijos. Este el cuadro que vivía ayer una familia cagüeña mientras la Policía y el Departamento de la Familia intervenían en la complicada tragedia familiar. Según la Policía, el niño sufrió una fractura craneal y otra en la base del ojo izquierdo, así como hematomas en el rostro cuando su padre, Julio Roldán Vega, de 30 años, le cayó encima a golpes. Se informó que la presunta agresión se produjo el lunes por la noche, cuando el niño se negó a bañarse. Roldán Vega, quien era camionero de la empresa Servi Metal, salió a toda prisa de su residencia a eso de las 8:30 de anteanoche y a las 6:30 a.m. de ayer fue encontrado ahorcado en una gomera aledaña a una gasolinera en Carolina, de acuerdo con las autoridades. El hombre, dijo la Policía, usó su auto de escalón, amarró una soga de nilón en una viga de la gomera y se dejó caer. Zujeila Almodóvar Valentín, de 23 años y madre del infante agredido, ofreció varias versiones al arribar al Hospital Hima de Caguas procedente de su residencia en la urbanización El Verde con el hijo herido y su hija de dos años, dijo la Policía. “Cuando llegó le dijo originalmente a una enfermera que el papá lo tiró contra una pared”, indicó la agente Nereida Sánchez. Luego, Almodóvar Valentín indicó a la Policía que ella estaba en la sala viendo televisión cuando escuchó al niño llorar en su cuarto. Alegó en esa segunda versión que no escuchó ningún ruido que le alertara de que algo extraño ocurría en el cuarto. Luego de dejarlo llorar un rato, fue a la habitación del niño y lo encontró boca abajo en la cama, sudoroso y botando sangre por la nariz y la boca. Entonces llamó a la Policía, informaron las autoridades. En esa segunda versión, la mujer evadió preguntas sobre la conducta de su esposo, informó la Policía. Dos vecinos de la familia dijeron a la Prensa, bajo condición de anonimato, que mientras Roldán Vega se montaba en su auto, su esposa le gritó: “te vas a morir por lo que hiciste” y “te voy a meter preso”. Sin embargo, esos mismos vecinos alegaron estar totalmente ajenos de que existiera un patrón de maltrato. Uno indicó que vio a la pareja jugando con los niños frente al apartamento al que se habían mudado recientemente. La agente Sánchez dijo que una hermana de Almodóvar Valentín le contó que en una conversación esa noche Almodóvar Valentín le dijo que Roldán Vega “le pidió perdón” por lo que hizo antes de marcharse de la casa. “Ella lo estaba protegiendo”, dijo la otra agente investigadora, Jeanette Ramírez Cáceres, de la División de Delitos Sexuales de Caguas. Ramírez Cáceres y Sánchez coincidieron en que la mujer podría ser acusada de negligencia. El caso sería consultado con la fiscal Dailú Rivera. Tras enterarse de la muerte de su esposo de cinco años, la mujer estalló en llanto pero no ofreció más información, dijo la Policía. “Ella no dice qué pasó”, dijeron las agentes. Contaron que la mujer aseguró que ni ella ni los niños eran víctimas de abuso por parte de Roldán Vega. Pero El Nuevo Día supo que la mujer le contó a una trabajadora social que su esposo castigó severamente a su hijo porque se negó a bañarse. En tanto, el niño, que fue transferido en la tarde al Hospital Pediátrico, está consciente pero con “letargo”, dijo la agente Sánchez. Agregó que apenas reacciona cuando se le habla y que sería atendido por un cirujano maxilofacial y un oftalmólogo. La secretaria de la Familia, Yanitsia Irizarry, dijo que logró, a través del Tribunal de Caguas, la custodia temporera del menor herido y su hermanita. Trabajadores sociales investigan el caso. Almodóvar Valentín ofreció información falsa, según la Policía, cuando alegó en el hospital que ella era testigo de un caso de asesinato. Igualmente ocultó que la pareja tuviera un tercer hijo de cinco años. Récord en Familia Irizarry señaló que la agencia investigaba si la familia tiene récord de maltrato. Confirmó que gestionaba la remoción de los menores del hogar. Una fuente dijo que Roldán Vega fue fichado en julio del 2009 por un caso de abuso a menores y que él y Almodóvar Valentín cedieron la custodia de un hijo que ahora tiene cinco años a un familiar que reside en Orlando, Florida, como parte de una cuerdo para retener la custodia de los otros dos niños. En esa ocasión, según la fuente, Roldán Vega “le partió un labio” al niño al que había dado su apellido por no ser su hijo biológico.Según fuentes, Almodóvar Valentín se expone a perder la custodia de sus dos hijos si se probase que son reincidentes en un caso de maltrato de menores. Este diario intentó, en vano, entrevistar a dos hermanas y dos tíos de Roldán Vega cuando lo fueron a identificar en el Instituto de Ciencias Forenses. Bueno T! eso fue todo... gracias por visitar mi post. comentar no cuesta nada.. Gracias.-
![Aprende a Programar [Guia Propia] Parte 1 - Resubido](https://storage.posteamelo.com/assets-adonis/assets/2016/12/03/8D4-i4qKMoB8CzR.webp)
Ok, ok. Se que el título de este post es tremendamente sensacionalista, algo extremo y hará que más de alguno entre a este post para colocar la imagen de No lei un Cara**, pero me arriesgare.Dando vuelta por Taringa, me di cuenta de que, a pesar de estar lleno de manuales sobre lenguajes de programación (C, C++, Java, PHP, ASP, .NET, etc), muy pocos post se enfocan a dar información para las personas que les interesa adentrarse en el mundo de la programación y desean saber como hacerlo y por donde partir.Es por esto que hoy, doy inicio a un post polémico y complicado que espero hacer muy completo y lo más simple que se pueda sobre como aprender a programar, desde una introducción con los conceptos más básicos hasta entrar de lleno a la programación en sí.Hago este post pues al ver el post de @emmaremix vi que muchos no sabian por donde empezar, y aqui les enseño todo con mis palabras para que puedan avanzar a crear sus juegos con el gran maestro que es @emmaremix.Lo que busco en el fondo es que quienes esten interesados, a través de este post puedan aprender a programar y no solo aprender a hacer programas.¿Están listos?, el viaje es largo y hoy solo es el posible primer post, así que busquen algo para comer, para tomar, armen una mochila de campamento y empaquen un par de calcetines, ya que nadie sabe lo que nos espera por delante.Antes de comenzar, para dejar todo bien claro:Yo no soy ni gúru ni profesional de la programación, por lo que no me atreveria a ofrecer este post como un método seguro llame sha, 100% garantizado, un abdomen mas plano en 7 días ni infalible. No utilizo ninguna guía ni manual oficial para redactar esto, pero lo hare lo más completo posible, a partir de las experiencias personales de como aprendi a programar e intentare traspasar todo eso en las siguientes líneas, por lo que están en todo su derecho de disputar los contenidos de este y los post siguientes y obviamente de seguir sus propios métodos si los estiman convenientes.Con eso claro, veamos lo que cubriremos en la primera parte de este post:Contenidos:¿Qué es la programación?.¿Qué necesito para aprender a programar?.Primeros pasos para aprender.Los algoritmos: la base de todo.Puede parecer poco, pero creanme que no lo es. Así que ya con todo eso definido, no hay más excusas, vamos. Esto es como andar en bicicleta, una vez que se aprende nunca se olvida.1.- ¿Qué es la programación?Hum… que pregunta más amplia. La verdad es que definir que es la programación puede enfocarse desde una serie de aspectos: Desde uno netamente técnico hasta uno más abstracto o conceptual, pero veamos.Mirandolo desde un aspecto netamente técnico o computacional, la programación es la realización de programas (dah!), es decir, la realización de una serie de instrucciones que interactuarán tanto con el hardware de nuestro computador, como con otras aplicaciones y/o el usuario que las maneje.En aspectos más simples aún, al programar en la mayoría de los casos lo que hacemos queda tan reducido como a preparar una serie de instrucciones y operaciones que nos permitan hacer una recolección de datos, operar con esos datos de alguna forma y luego presentar una serie de resultados producto de esas operaciones.Y finalmente mirandolo desde un aspecto más conceptual, la programación se refiere netamente a la resolución de problemas. Cuando programamos lo que queremos hacer es otorgar una solución a una inquietud, abordando aquel problema desde distintos puntos de vista hasta encontrar la respuesta más óptima y/o efectiva. De a poco iremos comprendiendo más esta definición.En los computadores, todo se maneja a base de números binarios (1’s y 0’s), por lo que cuando por ejemplo queremos realizar una suma, nuestro equipo no entiende si le decimos “suma 2 + 2″ sino que entendería una instrucción o serie de instrucciones en binario que le permita realizar la operación. Por eso cuando nosotros programamos, lo que hacemos es crear un intermediario entre el usuario que usa un lenguaje “real” y nuestro equipo que utiliza un lenguaje “de máquina”.¿Cómo hacemos esto?, bueno muy fácil (aunque no tanto): Los entornos de programación (tema que abordaremos más adelante en detalle) se encargan de realizar esa traducción de lenguaje real a lenguaje de máquina de las instrucciones que programamos y luego de vuelta la traducción de lenguaje máquina a lenguaje real de los resultados de las operaciones. Así que cuando vemos el resultado “4″ en pantalla es que nuestro equipo ha mandado el mensaje en binario y ha sido traducido por el programa que hicimos.Hasta ahora hemos visto conceptos algo complejos, pero no se preocupen, de a poco se irán entendiendo y en el fondo si no llegan a entender eso no limitará su capacidad de programación.2.- ¿Qué necesito para aprender a programar?Bueno… tiempo.Hablando un poco más en serio, podemos definir las necesidades en 2 tipos: las físicas y las “personales”.a) Necesidades físicas:¿Físicas?, ¿Say what?, ¿Es un concurso de popularidad? ¿Aliens? . No, en verdad por necesidades físicas nos referímos de cierta forma a “implementos reales o computacionales” que se utilizarán para empezar a programar. Para las primeras guías solo necesitaremos de nosotros mismos y a lo más una hoja de papel y un lápiz. (para jugar al gato en los ratos de ocio. No, ya verán porque). Eventualmente cuando nos adentremos más necesitaremos de estas cosas:Un computador (que si están leyendo me imagino que ya lo tienen).Un entorno de programación (que dependerá del lenguaje en el que decidamos programar. Ya lo veremos con más calma más adelante).Una conexión a Internet (no es de vida o muerte, pero si ayuda, si puedes jugar cs 1.6 online basta. ).Como pueden apreciar, no necesitamos nada de otro mundo. Son cosas que están accesibles a solo unos clicks de distancia (a menos que no tengan computador, ya que no pueden ir clickeando por la vida para comprarse uno. O sea pueden, pero cuesta más). Pero en todo caso no se preocupen por esos ítems aún, ya lo veremos con más calma cuando sea necesario.b) Necesidades “personales”:Personales es un término que utilizamos con bastante cuidado, ya que en verdad a lo que nos referimos es a una serie de características y habilidades (natas y/o adquiridas) personales que ayudan mucho en el aprendizaje. Si bien el no tener alguna de estas puede que termine por no ser un impedimento si sirve de mucho tenerlas. Nos referimos a:Paciencia, y mucha: Y hacemos mucho hincapié en este punto, por eso lo hemos puesto al tope de la lista. La programación puede llegar a ser muy frustrante y en muchas ocasiones podemos quedarnos pegados por un buen rato en la busqueda de una solución a un problema, por muy pequeño que sea. Más adelante daremos algunos consejos sobre esto. Lo importante es tener paciencia y entender que siempre hay baches en el camino, por muy buenos que lleguemos a ser.Perseverancia: Va ligado netamente al punto anterior. En la programación siempre hay que ser perseverante para poder lograr los objetivos que nos proponemos. En muchas ocasiones nos encontraremos con distintos problemas que van desde: no saber como afrontar un problema, hasta bloqueos mentales o desconocimiento. Saldremos adelante solo siendo perseverantes y solo continuando cuando pensemos que ya debemos tirar la esponja. Estas últimas 2 cualidades es lo que separa a los buenos programadores de los malos. No los conocimientos de lenguajes, sino la paciencia y la perseverancia es lo que los llevará a ser buenos.Mirar las situaciones desde distintos puntos: Esto es muy útil y nos refleja a nosotros mismos de como enfrentamos la vida. Cuando se nos presenta una situación de cualquier tipo, mientras de más puntos o lados la miremos y obtengamos ciertas conclusiones, aumentamos más la posibilidad de encontrar una buena solución. Debemos siempre tener en cuenta que todas las personas piensan de distinta forma y por lo tanto todos pensamos distintas soluciones y más aún, distintas formas de implementar estas soluciones. Si bien es siempre bueno definir hacia nosotros mismos una metodología para resolver los problemas, es muy útil tener la habilidad de abstraerse y mirar la situación desde otro lado. En más de alguna ocasión con esto obtendremos mejores soluciones que las que habiamos pensado originalmente.Pensar lógica y básicamente: Algún tiempo atrás, cuando estaba en el instituto, un profesor nos dijo “Señores, les contaré algo que nadie se ha atrevido a decirles hasta ahora: Estas máquinas que están frente a Uds. que son conocidas mundialmente como computadores capaces de hacer cosas que la mente humana no puede, son en verdad tremendamente básicas y tontas”. ¿Curioso, no?. Es una tremenda verdad. Los computadores son máquinas tremendamente estúpidas que saben realizar solo un par de operaciones básicas como cargar, grabar o sumar. Todo lo demás que pueden hacer es, o bien una combinación de esas operaciones, o el producto de otros programadores que han desarrollado aplicaciones que les permiten a estas máquinas realizar otros trabajos. ¿A qué vamos con esto?, a que siempre hay que tener presente lo básico de la forma de pensar de los computadores cuando programamos y por eso muchas veces debemos pensar igual de básico que ellos. Cuando necesitamos encontrar una solución, debemos enfrentar la situación como un computador lo haría sin saber otro tipo de informaciones que nosotros sabemos y debemos diseñar nuestras soluciones de la forma más básica para poder implementarlas.Ser estructurado: A pesar de que los programadores tienen la fama de ser medios “locos y volados” para encontrar solución a las respuestas, también son tremendamente estructurados. Y es que cuando pensemos una solución a implementar mediante programación, debemos pensarla estructurada de la forma: Bueno, para hacer esto, primero hay que hacer esto, luego esto, luego esto y finalmente esto. Ese orden y esa estructuración nos irá ayudando a no tener que volver sobre el mismo camino hecho para agregar cosas que deberían haber estado ahí.Conocimientos matemáticos: Si bien no es extremadamente necesario y no necesitamos ser unos magos de los números, ya que hoy con Internet tenemos acceso a la información de manera rápida y sencilla, si es bueno tener nociones matemáticas sobre operaciones, conocimientos algebraicos, geométricos ya que al programar utilizaremos uno o varios de estos conceptos en ocasiones.Ser curioso y tener disposición a resolver problemas: La programación nos presenta problemas, problemas y más problemas. Por eso es bueno tener curiosidad de como resolverlos de distintas formas y siempre tener la disposición a encontrar soluciones, en especial la más adecuada. Es nuestra curiosidad y nuestro espíritu de superación lo que eventualmente nos irá convirtiendo en mejores programadores.Es por esto que en las carreras relacionadas con el área de la computación e informática, previo a la programación siempre nos pasan (muchas veces odiandolo y sin entender bien porque) Cálculo y Álgebra. El primero nos enseña a expandir la mente y mirar los problemas desde distintos puntos y el segundo nos enseña a establecer una estructura de pensamiento. Así que ya saben, a dejar de odiar a esos viejos pelados (¿referencia personal?) que nos llenan de funciones, sistemas de ecuaciones y gráficos.Y finalmente un detalle a siempre tener en consideración: En la programación, siempre hay más de una forma de resolver los problemas.3.- Primeros pasos para aprenderSi hemos aguantado leer los primeros extensos parrafos llegamos al punto de: Ok, creo que tengo todo. Ahora ¿Cómo parto?. Bueno partamos con una pregunta que quizás no nos hemos hecho hasta ahora:¿Cualquier persona puede aprender a programar?Bueno, si y no. Según muchos “expertos”, hay gente que no sirve para programar. Si bien tienen razón hasta cierto punto creo, sin considerarme en lo más mínimo experto en el tema, que cualquier persona que tenga el interés y deseo de aprender puede llegar a hacerlo. Quizás no se puede garantizar a que llegue a ser realmente bueno, pero creo que teniendo las ganas, la paciencia, la perseverancia y el espíritu de superación se puede llegar muy cerca. Eso y harta práctica, que bueno, como para todo en la vida, nunca está demás.Entonces, ¿Por donde partimos?, por el principio por lo más básico. Partimos por empezar a preguntarnos ¿Cómo funcionan las cosas?. Me explico: Debemos empezar a entrenar nuestra mente y forma de pensar a descubrir como funcionan las cosas y como se resuelven los problemas. Para hacer esto hay una serie de formas y métodos, pero en el fondo debemos encontrar el que más nos acomode. Desde sentarnos en la vereda y ver como un conductor está haciendo funcionar su automóvil hasta abrir la calculadora de Windows y ver como es el modo de interpretar una operación que le indiquemos realizar. No necesitamos intentar descifrar el procedimiento exacto y detallado, si no que plantearnos esas inquietudes y ver como funcionan.Por ejemplo, cuando le decimos a la calculadora de Windows que realice una suma y le damos los datos, esta lo que hace es leer los datos que le dimos, interpretar cuales son números y cuales signos. En base al signo, ve la factibilidad de realizar la operación y la hace. Así de “simple”.Una vez que empecemos a entrenar nuestra forma de pensar de esa manera, podemos empezar a entrar a cosas mucho más concretas como el punto que viene a continuación.4.- Los algoritmos: La base de todo.¿Los algo-qué?. Algoritmos. . Wow..Los algoritmos son la base de la programación. Antes de entrar de lleno, pasemos a una definición:¿Qué es un algoritmo?Muchas veces se tiende a confundir un algoritmo con algo netamente computacional o tecnológico. En el fondo no es así.Un algoritmo es básicamente una lista definida, ordenada y finita que nos indica como resolver un problema determinado (¡Grande Wikipedia!), o sea un how-to bien básico y definido para una operación determinada.Si no quedó muy claro, utilizare un ejemplo que me ocurrio en el instituto:El mismo profesor que nos indicó la estupidez de nuestros queridos computadores, el día que nos quisó enseñar lo que eran los algoritmos, nos pidió el primer día de clases y sin darnos explicación alguna que definieramos el algoritmo para hacer un huevo frito.La cara de duda era unánime en los rostros presentes, ya que todos nosotros, sin experiencia previa, relacionabamos los algoritmos con procesos netamente computacionales, entonces no tenía lógica alguna. Luego nos otorgó la ayuda necesaria diciendonos: “Lo que necesito es que me definan lo que Uds. harían desde un principio para hacer un huevo frito”.Fue ahí donde nos dimos cuenta que uno puede definir algoritmos para cualquier tipo de procesos, desde los de la vida misma hasta cosas más evolucionadas y tecnológicas.Ahora, a diferencia de como uno ve los problemas en la vida real, al realizar un algoritmo sobre cualquier cosa, siempre es bueno plantearse los supuestos de cualquier problema que pudiese ocurrir y que soluciones se pueden establecer al respecto.¿A qué voy con esto?, a darnos cuenta de que los algoritmos son la premisa básica de cualquier solución de programación que vayamos a implementar. Con sus operaciones, sus supuestos, su contingencia y su desarrollo estructurado. Mientras más completos sean los algoritmos que nos planteamos, mejor será nuestra programación propiamente tal.Veamos un ejemplo, ¿les parece?, ya que después de tanta teoría vamos a marearnos un poco. Viendo la misma historia antes mencionada, intentemos hacer un algoritmo (básico) de como haríamos un huevo frito:Algoritmo para hacer un huevo frito:Voy a la cocina.Saco un huevo del refrigerador.Saco una sartén.Pongo un poco de aceite en la sartén.Hecho el huevo a la sartén.Lo frío.Me lo como.Si bien tenemos los pasos básicos establecidos de forma correcta, podemos empezar a ver de que nuestro algoritmo tiene ciertas fallas, como por ejemplo: ¿Qué pasa si no hay huevos?, ¿Qué pasa si no hay aceite?, ¿Qué pasa si no hay gas?. Pueden ser preguntas y respuestas algo básicas, pero reflejan lo que decíamos de plantearnos supuestos. Cuando programamos siempre tenemos que cubrir todos los aspectos necesarios, ya que por muy bien que conozcamos nuestro programa, el usuario y taringuero puede no saberlo todo, y es por esto que debemos estar preparados para cubrir cualquiera de estas situaciones. Una versión mejorada del algoritmo sería:Algoritmo para hacer un huevo frito 2.0:Voy a la cocina.Veo si hay huevos en el refrigerador.Si hay, saco un huevo y salto al paso 8Si no hay, voy a comprar.Para comprar, voy a buscar plata.Si hay plata, saco y voy al paso 8Si no hay plata, no se hace el huevo frito.Veo si hay gas.Si hay, prendo la cocina y voy al paso 14.Si no hay, busco dinero para pedir gas.Si no hay dinero, no hago el huevo.Si hay, encargo y salto al paso 14.Espero que llegue el gas.Saco una sartén.Si no hay sartén, no hago el huevo.Etc, etc.Creo que la idea se entiende. Si, es cierto, puede parecer excesivo ponerse en todos los supuestos y quizás estemos cubriendo aspectos sumamente extraños, pero mientras más situaciones que puedan ocurrir consideremos y tengamos soluciones presentes para eso, más completo será nuestro algoritmo y por ende nuestro programa.En el fondo siempre debemos pensar que existe la “mala intención de los usuarios o trolls en Taringa ”, un concepto que más adelante veremos en detalle y que es una de las cosas más importantes a tener en consideración por parte de los programadores.Es una excelente práctica empezar con el tema de los algoritmos. Empezar a plantearnoslos para resolver distintas situaciones, desde la vida cotidiana, hasta situaciones computacionales, linguísticas, de lógica, matemática, en realidad para todo. Siempre que hay un problema, hay un algoritmo que se pueda realizar para encontrar la solución.Así que los insto a practicar un poco este tema, mientras yo voy desarrollando la que será la segunda parte de este post para aprender a programar y no morir en el intento.Por ahora lo dejare hasta aquí, ya que he cubierto los aspectos más básicos y necesarios y han leído bastante. Es momento de descansar la vista un poco y seguir pensando, que es la mejor práctica posible.Si se interesaron en mi post, quizas haga muchas mas partes de “Como aprender a programar y no morir en el intento”, las cuales pueden llevar: Áreas de memoria alias “Como almacena la información una máquina”.Introducción al Pseudo-código.Haciendo nuestro primer programa.Todo, a la misma batihora, en el mismo baticanal.Como siempre, este tutorial ha sido desarrollado mediante mis conocimientos en la programacion , por lo que cuenta con mi, siempre seguro, con un poquito de gusto a limón y establecido Sello de Garantía. Cualquier problema, duda o comentario, sientanse libres de realizarlos en los comentarios y/o mandenme un MP. Asistire sus dudas a la brevedad posible.No hago este post con el fin de ganar puntos, solo lo hago para que tengan una base estructural en programacion y puedan de ahi en adelante crear sus juegos, programas, y quien sabe? quizas su sistema operativo que compita con Windows . Y recuerden, que pronto, conocerán a sus “mentes maestras”.Espero que este post haya sido de utilidad para Uds.Muchas gracias por leer y será hasta una próxima oportunidad.
![Aprende a Programar [Guia Propia] Parte 6](https://storage.posteamelo.com/assets-adonis/assets/2016/12/03/8D4-i4qKMoB8CzR.webp)
Continuando con mi (interminable ) solicitada saga de post orientada a quienes se empiezan a adentrar al mundo de la programación, hoy les traigo una nueva edición, realmente la última que veremos sobre Pseudo lenguajes (se que estan hartos ) y además las últimas consideraciones previas a la entrada a los lenguajes reales.Aprende a Programar [Guia Propia] Parte 6Nota: Tal como dice el título, esta es la 6ta parte de mis posts. Para un completo entendimiento, recomiendo, si no lo han hecho, leer los posts anteriores, los cuales pueden ser encontrados en mi perfil.Con eso claro, veamos los contenidos que cubriremos hoy:Contenidos:Funciones.Ultimas consideraciones sobre Pseudo-código.Entrando a un lenguaje real.Más sobre los paradigmas de programación.Como pueden apreciar, hay harto que cubrir, así que vamos directo a eso:1.- Funciones.El último tema que cubriremos sobre programación en pseudo-código propiamente tal, será el de las funciones, el cual es un elemento de suma importancia tanto para estas etapas tempranas como para cuando nos adentremos aun más en la programación.Intentare simplificar este tema lo que más pueda. De cualquier forma, a pesar de la complejidad que puede presentar, no se preocupen si no lo entienden a la perfección en un comienzo, ya que a medida que vayamos viendo los ejemplos y en otros contenidos más avanzados iremos comprendiendo bien este tema, aunque si siguen sin entender algunos puntos, no duden en pasarme un MP que con gusto respondere.Hasta ahora, cada vez que escribíamos un programa y dentro de el necesitábamos tener procedimientos de cálculo o manipulación de datos, los escribíamos línea por línea estructuradamente dentro del principal de nuestro programa, algo así:dijo:Definición de variable / asignación de valorOperación 1Operación 2Operación 3Asignación de resultadosSi las operaciones anteriores las necesitamos utilizar más de una vez o para distintas variables, adicionalmente podíamos añadirlas dentro de un ciclo, si el tipo de variables nos lo permiten, o bien repetir las operaciones dentro del programa las veces que sean necesarias.Ahora, si la operación es de una sola línea, como una operación matemática por sí sola, no presenta mayores complejidades ni costos repetirla todas las veces que sean necesarias. Sin embargo, cuando hablamos ya de un proceso que contiene varias operaciones, y por ende varias líneas de código, es cuando el tema se vuelve mucho más complejo y engorroso, ya que nuestros programas empiezan a aumentar de tamaño y será mucho más costoso (computacionalmente hablando) ejecutarlos. Para esto es que se definen las Funciones, las cuales, como su nombre lo indica, ofrecen la funcionalidad de agrupar y ejecutar una serie de operaciones, tanto por si solas como dependiendo de ciertos parámetros que les entreguemos, y a la vez dándonos la opción de retornarnos un valor que puede ser constante o variable dependiendo de los resultados de las operaciones y cálculos internos de la función.La programación está compuesta fundamentalmente de funciones, y hasta ahora, a través de los contenidos y ejemplos, hemos utilizado una serie de ellas. Por ejemplo, la parte principal que declaramos en cada programa que hacemos es una función, es la que contiene los contenidos principales del programa que escribimos, valga la redundancia. A esa función no le entregamos ningún tipo de parámetros y no nos retorna nada. Otras funciones que hemos utilizado hasta ahora son las iteraciones condicionales (Si, Si no), los ciclos (mientras, para, haga mientras) y otras como leer, mostrar, etc.Ahora, seguro muchos Taringueros se preguntaran: ¿Qué ventajas presentan las funciones?Principalmente orden, comodidad y economía. El uso de funciones nos permite no tener que repetir operaciones según el número de veces que las vayamos a necesitar y en vez de eso solo definirlas una vez y llamarlas cuando sea necesario. Eso también implicará que nuestro programa sea mucho más liviano al momento de ejecutarse. Existen una serie de otras ventanas que iremos descubriendo más adelante.Las funciones se escriben fuera de la función principal (normalmente por orden, se escriben después) y se definen de acuerdo a la siguiente estructura:dijo:tipo nombre_función(parámetro 1, parámetro 2, etc.){operación 1;operación 2;sentencia 1;sentencia 2;retorno de variable;}Donde:Tipo: Detalla el tipo de valores que devuelve la función. Estos tipos pueden ser los mismos que los de las variables, los cuales han sido especificados en mis posts anteriores. Sin embargo, no hay que confundirse, ya que por el hecho de que una función sea de un determinado tipo, no significa que dentro de las operaciones no puedan declararse y usarse variables de otros tipos, solo debemos fijarnos que las variables que retornamos si lo sean. Se debe definir un tipo para la función obligatoriamente.Nombre de la función: Es un nombre único, tal como si estuviésemos definiendo una nueva variable. El nombre de la función puede ser cualquiera, pero es recomendable, por orden, darle un nombre adecuado. Por ejemplo si definimos una función que encuentre el número máximo entre una serie de valores, es recomendable nombrar a esa función como numero_maximo. De esa forma, siempre podremos ver que hace cada parte de nuestro programa rápidamente cuando lo estemos revisando.Parámetros: Tal como he definido en distintas partes de mis posts, los parámetros que recibe una función son los que utilizará para operar dentro de ella y devolver resultados. Normalmente las operaciones declaradas en una función son procedimientos estándar que varían dependiendo de los valores que manejamos. En una función podemos recibir múltiples parámetros y estos pueden ser de distintos tipos, solo debemos asegurarnos de escribir primero el tipo y luego el nombre de ese parámetro, tal como si definiéramos variables. Estos nombres no pueden repetirse dentro de la función. (OJO con esto Taringueros)Operaciones y sentencias: Básicamente podemos hacer lo mismo que hacemos dentro de nuestros programas, ya sea usar operadores matemáticos, iteraciones condicionales, ciclos, mostrar, leer, etc. Todo está permitido.Valor a retornar: Esto es opcional, una función puede o no retornar un valor, ya que muchas veces el resultado podemos mostrarlo directamente en pantalla con la función mostrar. Si decidimos devolver un valor, lo hacemos mediante la sentencia retornar junto al valor o variable que enviemos. Solo debemos recordar que el valor o variable retornado tiene que coincidir con el tipo de la función.Con toda la definición ya más clara, veremos un ejemplo de declaración y uso de funciones:Ejemplo: Realizaremos un programa en donde crearemos una función que defina que número es mayor entre 2 entregados como parámetros. Los comentarios, como siempre, en negrita, cursiva y entre /* y */:dijo:Inicio/* Damos inicio al programa */Numero num1, num2, mayor;/* Declaramos 3 variables de tipo Número: num1 y num2 que serán 2 números que el usuario ingresará por teclado, y mayor, que será donde se almacenará el número mayor después de que la función nos devuelva el resultado */principal ( ){/* Declaramos la función principal del programa */mostrar(“Por favor ingrese el número 1: “);leer(%numero, &num1);mostrar(“Por favor ahora ingrese el número 2: “);leer(%numero, &num2);/* Mediante mostrar y leer, recibimos por teclado los 2 números ingresados por el usuario */mayor=numero_mayor(num1, num2);/* A la variable mayor, le asignamos el resultado de llamar a la función numero_mayor, especificada luego de la función principal, pasándole como parámetros las variables num1 y num2 */mostrar(“El número mayor de los que ingreso es: %numero”, mayor);/* Nuestra variable mayor ya recibió el resultado de la función, así que lo desplegamos */}numero numero_mayor(numero valor1, numero valor2){/* Declaramos una función de tipo numero, llamada numero_mayor y que recibe como parámetro 2 variables de tipo numero, llamadas valor1 y valor2, que corresponden a los num1 y num2 enviados desde arriba */Si(valor1 > valor2){retornar valor1;}Si no{retornar valor2;}/* Mediante una iteración condiciional, hacemos una comparación entre los 2 números y retornamos el mayor de los 2 para que se le asigne a la variable mayor y se muestre por pantalla al usuario. */}FinCon este simple ejemplo hemos podido apreciar un poco el funcionamiento y uso de las funciones en la programación. Hay un importante concepto que hemos utilizado ahora, pero que detallare más en profundidad cuando estemos hablando de lenguajes reales, que es el paso de parámetros desde una función a otra (lo que hicimos cuando llamamos a la función y lo que esta recibe por el otro lado). Por ahora no vale la pena entrar en esos detalles, pero ya los veremos más completamente.Con las funciones sucede lo mismo, esta pasada que le hemos dado ahora es bastante superficial, pero iremos cubriendo otros aspectos y descubriendo sus usos completos y más complejos a medida que vayamos programando más y más. Por ahora es una buena técnica ir combinando los otros contenidos que hemos visto en mis post anteriores con esto e ir practicando. Por ahora, al siguiente tema.2.- Últimas consideraciones sobre el Pseudo-código:En estos momentos que estamos llegando al final de nuestra cobertura sobre el pseudo-código o pseudo-lenguaje, es bueno repasar algunas consideraciones antes de adentrarnos al lenguaje real en el que decidamos programar, por ejemplo:1.- Recordemos que el pseudo-lenguaje no es un lenguaje de programación real, y por ende, lo que hemos cubierto hasta acá no lo encontrarán en libros o puede que aparezca de forma distinta. No se preocupen, el objetivo nunca ha sido ni será que nos convirtamos en expertos de pseudo-código, si no que entendamos como se desarrollan los procedimientos en la programación y como plantearnos soluciones a los problemas mediante el entendimiento de la estructura de los programas.2.- El pseudo-código, a pesar de no ser un lenguaje real, utiliza un paradigma estructurado y por la forma y palabras que normalmente se uilizan, se asemeja bastante al lenguaje C, por lo que es la opción natural para seguir. Veremos más de esto en el próximo punto.3.- Lamentablemente, al no tratarse de un lenguaje real, no existe ningún software que podamos utilizar para programar y así ver nuestros errores para poder solucionarlos. Esto por un lado es bueno, ya que agudiza nuestra forma para leer el código y detectar errores, algo que nos servirá de sobremanera más adelante.4.- Es recomendable que repasemos e intentemos entender de la mejor forma todos los puntos explicados en este y pasados posts de esta saga. Si bien hemos cubierto una pequeña parte de todo lo que comprende la programación, hasta ahora hemos visto las bases fundamentales para entender los lenguajes reales y todo el resto de aplicaciones dentro de la programación, por lo que entender de la mejor manera estas bases será esencial para que la enseñanza no se complique más adelante.3.- Entrando a un lenguaje real:Ahora que hemos de alguna forma “terminado” con el pseudo-lenguaje ha llegado un momento importante: Decidir el lenguaje de programación que empezaremos a aprender.Esta decisión no es sencilla, y depende de varios factores, entre ellos el paradigma de programación, la facilidad del lenguaje, la extensibilidad y funcionalidades, actualización con los tiempos e incluso preferencia personal entre muchas otras razones.Al momento de elegir debemos tomar esas consideraciones, aunque también fijarnos en otras como la documentación disponible, grupos de usuarios y todo lo que nos pueda apoyar a que el aprendizaje sea más sencillo.Como experiencia personal, y el camino que seguiremos en esta saga de posts, una de las mejores opciones para continuar es el lenguaje C, esto debido a lo similar que es al pseudo-código que hemos visto y porque ambos comparten el mismo paradigma estructurado, con lo que la transición se hace mucho más sencilla y así es posible pasar a otros lenguajes con mayor facilidad en el futuro. Así que prepárense, que para allá vamos.4.- Más sobre los paradigmas de programación:Tal como veíamos en este post, actualmente existen 4 paradigmas comunes de programación, como son (ojo Taringueros que son definiciones básicas, para que nos hagamos la idea de cada uno):Paradigma estructurado: Es el paradigma que hemos estado viendo hasta ahora con el pseudo-lenguaje y que luego veremos con C. Este paradigma, como su nombre lo indica, expresa una declaración y funcionamiento estructurado para sus programas, en donde desde arriba a abajo en una misma “plantilla de programa” debe estar el inicio, la declaración de las variables del programa y las funciones (la principal y otras funciones). Todo definido desde su inicio a su final. Además, los lenguajes estructurados se enfocan principalmente en el tratamiento de datos, recibiéndolos, operando con ellos y mostrando resultados. No tienen más profundidad que eso.Paradigma orientado a objeto: A diferencia del estructurado, en este paradigma, todo se trata como un objeto, cada uno de ellos con atributos, tal como si habláramos de objetos del mundo real. Los lenguajes de POO (programación orientada a objetos), operan mediante distintas clases, que son plantillas que determinan el comportamiento de un objeto. Pueden haber clases donde se determine un objeto, sus atributos y los métodos (parecido a las funciones) que se aplican a ellos y otras clases donde solo se encuentre el método principal (como la función principal). Este es un paradigma mucho más complejo que no queremos detallar por ahora para no confundirnos, porque el paso desde un lenguaje estructurado a uno POO complica al principio, pero no se preocupen, ya lo veremos.Paradigma orientado a eventos: En este paradigma se habla de lenguajes que dentro de un programa, presentan una serie de acciones que están “siempre listas” y se encuentran en espera para dispararse de acuerdo a un evento que ocurra (normalmente ejecutado por un usuario). Por ejemplo, tenemos programas como Word o Excel, que en sus menús y botones cuentan con múltiples mini-programas listos para ejecutarse cuando el usuario presione el botón o seleccione el menú. Por ahora no adentraremos más en esto, por las mismas razones el caso anterior.Paradigma orientado a aspectos: Este es un paradigma que actualmente se encuentra bajo investigación, por lo que no hay gran información disponible. Decidi mencionarlo más por anécdota que por cubrirlo propiamente tal. Quizás cuando estemos en posts futuros de esta saga podamos ir adelantando más información.Con esto podemos tener un poco más claro por qué existen distintos lenguajes de programación y que los diferencia, es principalmente su paradigma.Para casos de este post, por las razones antes descritas, seguiremos con el lenguaje C, el cual nos servirá de base para todo el aprendizaje que tendremos que hacer.Por ahora lo dejare hasta aquí, ya que hemos cubierto suficiente y es momento de tomar un descanso hasta posts futuros donde ya empezaremos a utilizar un lenguaje real de programación.En el próximo post:Introducción al lenguaje C.Variables en C.Funciones básicas.Iteraciones condicionales.Como siempre recuerden que este post ha sido hecho por:Espero que este post haya sido de utilidad para Uds.Muchas gracias por leer y será hasta un próximo post!
![Aprende a Programar [Guia Propia] Parte 8](https://storage.posteamelo.com/assets-adonis/assets/2016/12/03/8D4-i4qKMoB8CzR.webp)
Ya dejando un poco atrás la locura del FBI y MegaUpload , y preparándonos para recibir los nuevos rangos del karma este Lunes, he decidido hacer un alto del caos (en confabulación con mi “maravillosa” computadora que me ha fallado a diestra y siniestra, por lo que ofrezco mis disculpas ) y traerles un nuevo post de esta gran saga que ha sacado chispas buscando darles una pequeña manito durante sus primeros pasos del mundo de la programación.En mi post anterior, nos adentramos en nuestro primer lenguaje real, C, haciendo una larga introducción y comparación con lo que habíamos visto hasta ahora, terminando con nuestro primer programa. En esta ocasión, seguiremos adentrándonos más en el tema y terminaremos con la confección de un programa algo más complejo.Aprende a Programar [Guia Propia] Parte 8Nota: Como es habitual, les recomiendo, si no lo han hecho ya, leer los posts anteriores de esta saga, que pueden encontrar haciendo Click en mi perfil @ienrikex en la sección PostsTal como prometi en el post anterior, en este veremos los siguientes contenidos:Contenidos:1.-Comentarios.2.-Leyendo datos desde teclado.3.-Iteraciones condicionales.4.-Ciclos o búcles.5.-Ejercicio: Programando un terminal de venta simple.Veremos bastante hoy, así que vamos, manos a la obra Taringueros!:1.- Comentarios.Si se han fijado hasta ahora, siempre que realizo algún ejemplo o ejercicio de código, en C, Pseudo-código o bien en mis posts de esta saga, siempre pongo las explicaciones entre unos símbolos /* y */.Esto, junto a otros símbolos, es lo que en la programación (a todo nivel) se conoce como comentarios.Los comentarios en la programación, si bien no son obligatorios, se convierten en una herramienta util y su mayor función es entregarnos la posibilidad de añadir pequeñas anotaciones sobre lo que estimemos conveniente, ya sea sobre el código propiamente tal u otras cosas como notas de autoría o funcionamiento del programa en sí.]Pero @ienrikex ¿Por qué usas comentarios?Principalmente por un tema de orden. Tenemos que pensar de que si bien nuestra memoria puede ser excelente, en más de alguna ocasión nos tocará revisar códigos que hayamos realizado hace algún tiempo y puede que en ese programa hayamos utilizado alguna función o lógica que no tiene sentido en este momento. Por eso el uso de comentarios nos simplifica el tener que estar mucho tiempo deduciendo lo que alguna vez hicimos. Lo mismo se presta para cuando nuestro código es revisado por terceros o bien nosotros revisamos códigos hechos por alguien más.Hay 2 formas de comentarios: los de línea simple y los de múltiples líneas. La única diferenciación es en los símbolos que utilizamos para iniciar y terminar los comentarios.Cuando los comentarios son de línea simple solo debemos añadir al principio de la línea el símbolo // . Debemos tener en cuenta de que solo será válido como comentario lo que escribamos en la misma línea. Si pasamos a otra línea lo tomará como código y nos lanzará error, por lo que debemos utilizar símbolo de comentario de múltiples líneas.Para múltiples líneas, utilizamos el mismo que hemos usado hasta ahora, o sea al principio del comentario ponemos /* y al final del comentario cerramos con */. Todo lo que escribamos entremedio será considerado como comentario.De cualquier forma, si es que les complica recordar los símbolos para cada caso, pueden utilizar siempre el formato de múltiples líneas, que cubre comentarios ya sea en 1 línea o en varias.2.- Leyendo datos desde teclado.Antes de registrarme en Taringa!, cuando trabajaba en Pseudo-código, una de las funcionalidades que más utilizaba, era la lectura o recepción de datos ingresados por un usuario vía teclado. Eso me permitía interactuar de una mayor forma con quien utilizaba el programa y realizar procesamientos mucho mejores y personalizados.Pues bien, en C también podemos leer datos desde teclado, de una forma tan similar como en pseudolenguaje. Si recordamos el post anterior, hablaba de la función scanf, la cual nos permitía realizar esa tarea y que se utiliza de la siguiente forma:dijo:scanf(“%tipodevariable”, &nombredelavariable);Como podemos observar, esta función presenta 2 parámetros: %tipodevariable (entre comillas) y &nombredelavariable, los cuales a su vez presentan 2 signos: % y &. Voy por parte explicando:tipodevariable: Tal como han visto en numerosas ocasiones, cada variable que definimos en un programa contiene un tipo de datos que puede almacenar (int, float, char, etc). A su vez, el lenguaje C utiliza unos simbolos que representan esos tipos y que se incluyen en las funciones scanf y printf para decirle al compilador que tipo de dato es el que estamos leyendo/mostrando. Estos simbolos son la d para variables de tipo int, la f para variables de tipo float y la c para variables de tipo char entre otras.El símbolo %: Este símbolo siempre debe ir por obligación acompañando a los símbolos indicados en el punto anterior, de esta forma el compilador comprenderá que estamos hablando de un tipo de dato y no de una consonante por sí sola.nombredevariable: Es el nombre que le damos a una variable en particular cuando la definimos.El símbolo &: En el lenguaje C, cuando utilizamos el símbolo & junto al nombre de una variable, le estamos diciendo al compilador que nos estamos refiriendo al área de memoria en el que esa variable almacena su información. Como dijimos hace algún tiempo, toda variable al momento de ser creada, apunta a un área de memoria interna del computador para manipular su información. A esta área accedemos con el símbolo & cuando leemos un dato.Con esas definiciones claras, veamos un pequeño ejemplo, para lo que utilizaremos el entorno de programación que instalamos en el número anterior:Ejemplo: Realizar un programa que lea un dato numérico por teclado y luego mostrarlo por pantalla. (La explicación del código, como siempre en negrita, cursiva y entre /* y */.dijo:#include <stdio.h>#include <stdlib.h>#include <conio.h>/* Partimos por agregar las librerías necesarias para nuestro programa, incluida la conio.h para hacer uso de la función getch( ); */int numero;/* Declaramos una variable llamada numero de tipo int */int main( ){/* Declaramos la función main o principal */printf(“Ingrese un numero del 1 al 10: “);/* Mostramos un mensaje al usuario para que ingrese un numero del 1 al 10 */scanf(“%d”, &numero);/* Con scanf leemos el dato, indicando con %d que es un dato de tipo int e indicamos que guardaremos la información en el área de memoria de la variable numero poniendo &numero */printf(“Ingreso el numero %d”, numero);getch();/* Mostramos el numero que ingreso el usuario, poniendo un mensaje con printf y en la posición donde mostraremos el número ponemos el símbolo correspondiente al tipo de dato, o sea %d, y luego de la coma la variable que mostraremos. En la línea siguiente ponemos un getch ( ); para que el programa quede en espera hasta que presionemos una tecla y así podamos ver el resultado antes que se cierre */} // Cerramos llave de la función main.Compilamos el programa y no deberíamos tener errores. Lo ejecutamos y probamos que funcione.Así de simple es la captura de datos vía teclado.3.- Iteraciones condicionales.Las iteraciones condicionales en C son bastante similares a las que vimos en pseudocódigo (Si y Si No, Switch) y cumplen exactamente la misma función, esto es, ejecutar una serie de acciones a partir del cumplimiento de una condición. No entraremos en mayor detalle, pues lo vimos de forma bastante completa en el pasado.En lo que si adentraremos es en como se usan en C:Si y Si noEn C se utiliza de la misma forma, radicando la diferencia en que en vez de ser Si y Si no, hablamos de if y else. Esta iteración tiene las mismas características que en pseudo, o sea, todo else debe ir luego de un if y dentro de un if y de un else pueden ir múltiples if y elses. La forma de declaración es:dijo:if(condición){sentencia 1;sentencia 2;}else{sentencia 3;sentencia 4;}Cuando utilizamos if y else, podemos o no usar llaves para abrir y cerrar el if. Cuando un if y/o un else tienen solo una sentencia a ejecutar, podemos escribirlos sin llaves para abrir y cerrar. Si es más de una sentencia, necesariamente deben llevar llaves. Si desean, para evitar confusiones, podemos utilizar siempre las llaves.Veamos un ejemplo ampliando el caso anterior. También pediremos un dato al usuario, pero en vez de mostrarlo lo someteremos a un simple if y else para ver si el número es mayor a 5:dijo:#include <stdlib.h>#include <stdio.h>#include <conio.h>int numero;int main(){printf(“Ingrese un numero del 1 al 10: “);scanf(“%d”,&numero);/* Primero vemos con un if si el numero es igual a 5. Recordemos que para comparar utilizamos doble signo igual */if(numero==5)printf(“El numero ingresado es 5″);else // Si no es igual a 5if(numero > 5) // Si es mayor a 5 mostramos el mensajeprintf(“El numero ingresado es mayor a 5″);else // Si es menor a 5 mostramos el mensajeprintf(“El numero ingresado es menor a 5″);getch();}A medida que vayamos avanzando, el uso de if y else será más complejo y largo, pero la lógica es básicamente la misma.La iteración switch la veremos en el próximo número, ya que implica un mayor nivel de detalle y no queremos extendernos por sobre los demás contenidos de momento.4.- Ciclos o búcles.Tal como las iteraciones, en pseudolenguaje también definimos y utilizamos ciclos y búcles que cumplen la misma funcionalidad que en C, por lo que no nos desviaremos definiendo nuevamente esos temas, si no que veremos cada caso para C y luego un ejemplo que los reune a todos.MientrasEl ciclo mientras que usabamos en Pseudocódigo, en C (y otros lenguajes) es conocido como while y es uno de los más usados. La forma de utilizarlo es la misma, o sea:dijo:while(condición){sentencia 1;sentencia 2;}Tal como en Pseudo, este ciclo sólo se ejecutará (y se mantendrá en ejecución) mientras la condición se cumpla.ParaEste ciclo en lenguaje C es conocido como for y se utiliza de la misma forma, o sea:dijo:for(inicialización de variable ; condición ; aumento o decremento de la variable){sentencia 1;sentencia 2;sentencia 3;}Tal como en el caso del ciclo while, este ciclo se continuará ejecutando mientras se cumpla la condición, pero a diferencia del anterior, este siempre se ejecutará, ya que la variable para la condición se inicializa dentro del propio ciclo.Haga mientrasCorresponde al ciclo do-while, bastante similar al caso del while pero con 2 diferencias. Este ciclo se ejecutará al menos 1 vez aunque la condición no se cumpla y el while del final debe ir con punto y coma, o sea:dijo:do{sentencia 1;sentencia 2;sentencia 3;}while(condición);Tal como en pseudolenguaje, hay ocasiones ideales para el uso de cada tipo de ciclo, pero en muchas ocasiones podemos usar cualquiera de los 3 y dependerá más que nada del gusto personal.A continuación veremos un ejemplo en donde utilizaremos los 3 ciclos para resolver un mismo problema.Ejercicio: Enumerar del 1 al 10 utilizando los 3 ciclos vistos hasta ahora.dijo:#include <stdlib.h>#include <stdio.h>#include <conio.h>int numero;int main(){numero=1; // Asignamos el valor inicial a la variablewhile(numero<=10) // Partimos con un ciclo while{printf(“%dn”,numero); /* Mostramos el número y utlizamos n para hacer salto de línea */numero++; // Incrementamos el valor}for(numero=1;numero<=10;numero++) // Seguimos con un ciclo for especificando los parámetros{printf(“%dn”,numero); // Mostramos el número}numero=1; // Reinicializamos el número a 1do // Terminamos con un ciclo do-while{printf(“%dn”,numero); // Mostramos el númeronumero++; // Incrementamos el valor}while(numero<=10); // Definimos la condicióngetch(); // Dejamos el programa en espera}Luego de compilar y ejecutar podemos ver que como resultado se enumerará del 1 al 10, 3 veces seguidas, 1 por cada ciclo que definimos.5.- Ejercicio: Programando un terminal de venta simple.Ahora que hemos visto aspectos básicos del lenguaje C, desarrollare un ejercicio en el que combinaremos todos los conocimientos adquiridos hasta ahora.Lo que haremos será programar un terminal de venta simple, en donde primero desplegaremos una lista de productos, luego pediremos el código del producto, la cantidad que se desea llevar y mostraremos el total a cancelar. No nos complicaremos mucho y en el futuro iremos añadiendo nuevas funcionalidades. Así que manos a la obra:dijo:#include <stdlib.h>#include <stdio.h>#include <conio.h>int codigo, cantidad, valor, total, vuelto, pago; /* Declaramos las variables que usaremos, todas de tipo int */int main(){printf(“t Lista de productosn”); /* Partimos por listar los productos, utilizamos t para separar los textos, tal como si utilizaramos la tecla TAB */printf(“Codigot Nombret Precion”);printf(“1t Sillat 100n”);printf(“2t Puertat 350n”);printf(“3t Sillont 200n”);printf(“nIngrese el codigo del producto que desea llevar: “); /* Solicitamos el código del producto*/scanf(“%d”,&codigo); /* Leemos el código */printf(“nIngrese la cantidad que desea llevar: “); /* Solicitamos la cantidad que llevarán */scanf(“%d”,&cantidad); /* Leemos la cantidad */if(codigo==1) /* Comparamos mediante iteraciones el código para asignar el valor total */valor=100;if(codigo==2)valor=350;if(codigo==3)valor=200;total=valor*cantidad; /* Multiplicamos el valor por la cantidad para obtener el total */printf(“nEl total es de: %d”,total); /* Mostramos el total */printf(“nIngrese el pago: “); /* Solicitamos el pago */scanf(“%d”,&pago); /* Leemos el pago */if(pago<total) /* Vemos mediante un if si el pago es suficiente */printf(“nEl pago no es suficiente”);else{vuelto=pago-total; /* Obtenemos el vuelto */printf(“nEl vuelto es de: %d”,vuelto); /* Mostramos el vuelto */}printf(“nVenta finalizada”); /* Damos el mensaje de despedida */getch();}Y así tenemos nuestro simple terminal de venta. Como podemos apreciar, este programa no es lo suficientemente óptimo, ya que solo podemos realizar 1 venta por sobre 1 sólo producto, así que su aplicación es bastante limitada. Para poder realizar múltiples ventas o 1 venta de múltiples productos es necesario el uso de ciclos para poder repetir las acciones necesarias.Desde ya los incentivo a que vayan modificando este programa y agregando esa funcionalidad. De cualquier forma en mis próximos posts les ire añadiendo más y más cosas a este programa para crear una aplicación mucho más completa.Con esto doy por terminado el post de hoy, hemos cubierto bastante y aún nos queda un largo camino por recorrer, así que mucha paciencia.En el próximo post de @ienrikex veremos:Iteración Switch.Vectores.Matrices.Terminal de venta – 2da parte.Recuerden que como siempre, este post ha sido hecho por:]Espero que este post haya sido de utilidad para Uds.Muchas gracias por leer, y será hasta un próximo post
Quizás recuerden hace algún tiempo que el buen @ienrikex les mostro el camino a seguir para empezar a programar en sus posts. Ésta vez y por petición expresa de (nadie, bueno, @NegroBurgundy ) de millones de personas, les traigo lo mismo, pero ésta vez en otro lenguaje, el siempre presente y nunca querido C. Cómo generar números aleatorios en C ¿Qué necesitamos? Un editor de lenguaje C, tipo Borland C++. ¿Cómo procedo @ienrikex? 1.- Primero explicare algunos conceptos: En C, existe una función llamada rand(), que genera números aleatorios. El problema que tiene esta función es que siempre que reinicies el programa, aparecerán los mismos números. Para evitar esto, hay que darle un número “semilla”, el cual operará como base para la generación de la secuencia de números. El problema con esto, es que si le damos un número fijo, volvemos al problema anterior, ya que siempre utilizará la misma base definida y por ende la secuencia será la misma. Entonces, lo que necesitamos es darle un número “semilla” dinámico, esto es, que vaya cambiando cada vez que ejecutemos el programa. Sabiendo esto, la función que da la semilla a rand() es srand(), que recibe como parámetro (lo que va entre los paréntesis) el número semilla, que en este caso, será la hora del sistema en segundos. Así, a menos que el programa se ejecute 2 o más veces en menos de un segundo, los números cambiarán. La función para saber la hora actual del sistema es time(NULL). Sabiendo esto, vamos al código. Haremos un generador de números aleatorios, donde la cantidad de estos, la decidirá el usuario, ingresando esta cantidad por teclado. dijo:#include<stdio.h> // libreria basica para entrada y salida #include<stdlib.h> // libreria para el uso de rand() #include<conio.h> // libreria para el uso de getch() #include<time.h> // libreria para el uso de time() void main( ) { // Declaracion de variables int numero,cantidad,contador; int hora = time(NULL); // Semilla de rand(); srand(hora); /* Recogemos por teclado la cantidad de numeros que quiere el usuario */ printf("Ingrese la cantidad de numeros aleatorios que desea generarn"; scanf("%d",&cantidad); /* Generamos un ciclo que se repite la cantidad de veces indicada. En cada vuelta del ciclo se genera y se imprime un numero aleatorio. */ for(contador = 0; contador<cantidad; contador++) { numero = rand()%100; printf("%d ", numero); } getch(); // genera una pausa en la ejecucion del programa } A pesar de que esta explicado con comentarios, desmenucemos un poco. dijo:#include<stdio.h> // libreria basica para entrada y salida #include<stdlib.h> // libreria para el uso de rand( ) #include<conio.h> // libreria para el uso de getch( ) #include<time.h> // libreria para el uso de time( ) Estos cuatro includes, son para llamar a las librerías necesarias para ejecutar el programa. La librería conio.h, no es necesaria para que el programa funcione, solo la llamamos pasar usar la función getch( ) y generar una pausa en el programa. Con esto podremos ver el resultado por pantalla antes que se cierre el programa. texto planocopiar codigoimprimir? // Declaración de variables int numero,cantidad,contador; int hora = time(NULL); Acá declaramos el tipo y que variables utilizaremos. Definimos 4 variables de tipo int (entero), 3 de ellos sin inicializar (es decir, sin valor inicial) y una de ella inicializada. Las 3 sin valor inicial, serán el número aleatorio que se genera (número). La cantidad de números aleatorios que se generarán (cantidad) y un contador para crear un ciclo. texto planocopiar codigoimprimir? // Recogemos por teclado la cantidad de numeros que quiere el usuario printf("Ingrese la cantidad de numeros aleatorios que desea generarn"; scanf("%d",&cantidad); Mostramos por pantalla el mensaje para el usuario y asignamos el valor que se ingrese, a la variable cantidad usando el símbolo & (ampersand). texto planocopiar codigoimprimir? // Generamos un ciclo que se repite la cantidad de veces indicada // en cada vuelta del ciclo se genera y se imprime un numero aleatorio. for(contador = 0; contador < cantidad; contador++) { numero = rand()%100; printf("%d ", numero); } getch(); // genera una pausa en la ejecucion del programa } Aquí es donde generamos el ciclo, con el bucle for. Tenemos 3 parámetros separados por ; (punto y coma), en el primero inicializamos la variable contador con el valor cero. En la segunda ponemos la condición que se debe cumplir para terminar el ciclo, en este caso decimos que el ciclo se repita siempre que contador sea menor que cantidad. Ojo, aquí decimos que sea menor que el número porque el valor inicial es cero y empezamos a contar desde cero y no de uno. Al final aplicamos un getch( ) para detener el programa y lograr ver los resultados. Les invito a realizarlo y hacer sus aportes en los comentarios, sin bardo ni descontrol. Cualquier consulta o comentario que puedan tener, no duden en dejármelos unas líneas a continuación. Como siempre, este post ha sido: Por ahora, Me despido. Saludos