lunes, 23 de julio de 2007

Ingeniería Inversa

H0ax [hoax_ws@yahoo.es]

Recientemente, hablando con un colega del lugar donde trabajo, acerca de las mejores maneras de proteger un producto contra las técnicas de cracking, me vino el recuerdo de aquellos días en los que me interesé por primera vez en el tema, no como programador que protege su producto, sino como usuario que lo desprotege para uso propio sin costo alguno (por Dios, ¿quién ha pagado aquí por un software?). Claro que en aquel entonces mi enfoque era muy distinto al de ahora.

Resulta que una vez fui atacante, y ahora puedo ser atacado, lo cual no es un gran problema, si consideramos que conozco las armas de mi enemigo, sé cómo las usan, y más aún, las he usado. La verdad, hace ya tiempo que no practico el cracking; antes lo hacía por diversión -nunca por necesidad-, ya que todo lo que he crackeado ya ha sido trabajado. Lamentablemente, lo que no se ejercita se olvida y con el tiempo vamos perdiendo las facultades que menos usamos, así que si escribo este artículo es para no olvidar y ya de paso les brindo a ustedes la posibilidad de conocer esta arma tan fina, precisa y poderosa, que es la ingeniería inversa.

Lo que vamos a hacer es una práctica muy sencilla y bastante elemental. Probablemente muchos hayan oído hablar del método "74/75", una técnica muy básica, pero increíblemente útil y, particularmente yo, no sólo la he usado para quebrantar sistemas de verificación de números de serie, sino para muchas cosas más.

Primero lo primero, ¿a qué nos enfrentamos? Bueno, a partir de ahora nuestro enemigo número uno será aquel cuadro con dos cajas de texto y dos botones al cual le insertas algo como un nombre de usuario y un serial y mágicamente, por una razón que parece contradecir las leyes naturales que rigen nuestro mundo, casi siempre nos dice lo mismo: "Los datos suministrados no son los correctos, verifique y vuelva a intentarlo". Este es un escenario clásico, lo del nombre de usuario y el serial pude cambiar, pues algunos sólo piden una sola cosa: el serial; el mensaje de error puede ser diferente, en fin, la variedad se manifiesta entre estos odiosos cuadros de diálogo.

Segundo paso: conoce a tu enemigo, y aquí surge la segunda pregunta, ¿cómo funciona? Como ya he dicho, la variedad se manifiesta en todo su esplendor, pero limitándonos al escenario clásico, el funcionamiento es el siguiente: el programa recibe un nombre de usuario; luego, partiendo del mismo, genera un código que comparará con el número de serie; de ser iguales, ¡felicidades!, puedes usar el producto, si no, tendrás que sentarte a leer uno de esos tutoriales de cracking, lo que me recuerda por qué estás leyendo este artículo.

También está el otro caso que te pide sólo el serial, difícil de encontrar, demasiado pobre e ineficiente, muy fácil de crackear, así que ya casi nadie lo usa. Más tarde hablo de él.

Hasta ahora sabemos que al proporcionarle mi nombre al programa, éste genera el serial a partir del mismo y luego compara el que obtuvo con el que yo le dí. Llevemos eso a los códigos.

El esquema básico puede verse así:

// si el serial es bueno
if ( Serial_Entrado == GetSerial( Nombre_Entrado ) ) {
    // gracias por usar un buen keygen
  MessageBox( NULL, "Gracias por usar nuestro programa, bla bla", "Registro oK", NULL );
    // quita restricciones
  ...
} else { //si no
    // el serial no sirve
  MessageBox( NULL, "Los datos entrados no son correctos.", "Error", NULL );
}

Los códigos pueden cambiar, pero en esencia, la mayoría lucirán como éste, en especial si el programador no quiere pasar trabajo con algoritmos complicados.

Aquí vemos cómo el nombre de usuario ( Nombre_Entrado ) es pasado como parámetro a la función imaginaria GetSerial. Esta función se encarga de generar a partir de cada caracter de Nombre_Entrado un string, que es nuestro número de serie. Obviamente, cada nombre tendrá su propio serial.

Pasamos ahora al plan de ataque. Ya sabemos más, sabemos que nuestra felicidad depende en estos momentos de un if, o sea, una condicional. Por muchos intentos que tengamos disponibles, las posibilidades de acertar con el verdadero código son irrisorias, por lo tanto, ¿qué hacemos? Pues invertimos la condicional de la siguiente manera:

//si el serial NO es bueno
if ( Serial_Entrado != GetSerial( Nombre_Entrado ) ) {
    //gracias por registrarte
  MessageBox( NULL, "Gracias por usar nuestro programa bla bla", "Registro oK", NULL );
    //quita restricciones
  ...
} else { //si es bueno
    //mensaje de error
  MessageBox( NULL, "Los datos entrados no son correctos.", "Error", NULL );
}

¿Dónde esta el cambio? El operador de la condicional cambió de == a != -para aquellos que no conozcan el lenguaje C, != equivale a <> en otros lenguajes-. ¡Listo!, ahora cualquier serial que escribamos será válido, cualquiera excepto el verdadero :0. Bueno, qué más da, si las posibilidades de acertar son despreciables.

Es aquí donde todos me acusan de loco y me recuerdan que no tengo el código fuente del programa. Lo cierto es que quizás no tengamos los códigos en C, ni en lenguajes de alto nivel, pero sin dunda alguna tenemos los códigos en ensamblador, y es allí donde vamos a hacer los cambios, directamente en el hexadecimal del programa.

Aquellos que conocen de ensamblador, sabrán que las condicionales se definen usando las instrucciones JE, JZ ("Jump If Equal", "Jump If Zero") y JNE, JNZ ("Jump If Not Equal", "Jump If Not Zero") seguido de la dirección de saltos y antecedido de un TEST o un CMP, que determina lo que se está comparando.

El caso es que JE, codificado en hexadecimal, es 74 y JNE, 75; de ahí el nombre "74/75" para esta técnica. Cambiaremos un JE por un JNE, o un JNE por un JE, 74 a 75 ó 75 a 74, la idea es invertir la condicional a nuestro favor.

Ya concluyendo la introducción del artículo y entrando en el área práctica, haré un comentario. Para tener éxito en el mundo de la ingeniería inversa, poseer conocimientos de ensamblador es fundamental; mientras mejor domines el ASM, mejor podrás rastrear el código de un programa, hasta el punto de sentirte tan cómodo leyendo el código en ASM como si lo estuvieras leyendo en C o en otro lenguaje de alto nivel. No obstante, si no sabes nada de ASM, sigue leyendo igual. Cuando yo empecé en el tema del cracking tampoco sabía nada de ensamblador, de hecho, mis inicios en ASM fueron gracias al cracking. Como principiante no necesitas saber escribir programas en ASM para tener éxito, pero sí es muy importante que sepas cómo funciona lo básico, que conozcas las principales instrucciones, los registros del microprocesador, etc. Luego, con el tiempo, puedes profundizar y, si te interesa, empezar a usarlo para programar.

Vamos a la práctica. Para empezar, permítanme presentarles a nuestro enemigo, un pequeño CrackMe que acabo de preparar para este fin; servirá bien de conejillo de indias. Este es el código en C:

/*
**
**Nombre: CrackMe.c
**Autor: h0aX
**Fecha: 17-julio-2007
**
**Descripción: Nuestro conejillo de indias
**
**
*/

#include
#pragma hdrstop
#pragma argsused

HWND hwndMain, hwndButton1,
     hwndButton2, hwndButton3,
     hwndEditUser, hwndEditSerial;

HINSTANCE hInst;

void GetSerial( char *szName, char *szSerial )
{
  int i, cont;
  memset( szSerial, 0, 255 );

  cont = 0;

    /* Aquí se genera el serial a partir del
    ** nombre de usuario. Este es un ejemplo
    ** sencillo, así que simplemente invertiremos
    ** el nombre de usuario y le ponemos un punto
    ** al principio de la cadena, ej:
    ** usuario: test serial: .tset
    */
  for ( i = strlen(szName) ; i >= 0; i-- ) {

    strcat(szSerial,".");
    szSerial[cont] = szName[i] ;
    cont++;
  }
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
  switch (uMsg) {
    case WM_COMMAND: {
 
    // botón registrar
    if (hwndButton1 == (HWND) lParam) {
      char szUserName[255];
// usuario entrado
      char szSerial[255];
// serial verdadero
      char szSerial_Entrado[255];
// serial entrado
     
// obtiene los datos
      GetWindowTextA( hwndEditUser, szUserName, 255 );
      GetWindowTextA( hwndEditSerial, szSerial_Entrado, 255 );
     
// chequea si no hay nada en blanco
      if ( ( !strcmp( szSerial_Entrado, "" ) ) || ( !strcmp( szUserName, "" ) ) ) {
        MessageBoxA( hwndMain, "Datos en blanco.", "Error", MB_ICONERROR );
        return 0;
      }

      // genera el serial a partir del usuario
      GetSerial( szUserName, szSerial );
      
// y he aquí nuestra preciosa condicional
      if ( !strcmp( szSerial_Entrado, szSerial ) ) {
        MessageBoxA( hwndMain, "Serial correcto, felicidades.", "Registro oK", MB_ICONINFORMATION );
 
           // quita restricciones, bla bla ...
      } else {
        MessageBoxA( hwndMain, "Los datos no son correctos.", "Error", MB_ICONERROR );
      }
    } else
  
    // botón cancelar
    if (hwndButton2 == (HWND) lParam) {
      PostQuitMessage(0);
    } else
 
    // botón acerca de
    if (hwndButton3 == (HWND) lParam) {
      MessageBoxA( hwndMain, "CrackMe por h0aX para \r\nla revista "
      "BlackHat,\r\npruebas de ingenieria inversa."
      "\r\n\r\n[17-julio-2007]",
      "CrackMe por h0aX", MB_ICONINFORMATION );
    }
    return 0;
  }
  case WM_DESTROY: {
    PostQuitMessage(0);
    return 0;
  }
 }
 return DefWindowProcA(hwnd,uMsg,wParam,lParam);
}

WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  MSG msg;
  WNDCLASS wndclass;
  char szClassName[] = "hXClass_CrackMe";
  hInst = hInstance;
  wndclass.style = CS_VREDRAW | CS_HREDRAW;
  wndclass.lpfnWndProc = WndProc;
  wndclass.cbClsExtra = 0;
  wndclass.cbWndExtra = 0;
  wndclass.hInstance = hInstance;
  wndclass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
  wndclass.hCursor = LoadCursorA(NULL, IDC_ARROW);
  wndclass.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
  wndclass.lpszMenuName = NULL;
  wndclass.lpszClassName = szClassName;
  RegisterClassA(&wndclass);
  hwndMain = CreateWindow(szClassName,"CrackMe por h0aX", WS_SYSMENU |     WS_MINIMIZEBOX | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 290, 180, NULL, NULL, hInstance, 0);
 
CreateWindow("Static","Nombre de usuario:", WS_VISIBLE | WS_CHILD, 15,10, 250,15, hwndMain, 0, hInst, NULL);
  hwndEditUser = CreateWindowEx(WS_EX_CLIENTEDGE,"Edit","", WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL, 15,30, 250,22, hwndMain, 0, hInst, NULL);

   CreateWindow("Static","Serial:", WS_VISIBLE | WS_CHILD , 15,60, 250,15, hwndMain, 0, hInst, NULL);

  hwndEditSerial = CreateWindowEx(WS_EX_CLIENTEDGE,"Edit","", WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL , 15,80, 250,22, hwndMain, 0, hInst, NULL);

  hwndButton1 = CreateWindow("Button","Registrar", WS_VISIBLE | WS_CHILD, 15,110, 75,25, hwndMain, 0, hInst, NULL);

  hwndButton2 = CreateWindow("Button","Cancelar", WS_VISIBLE | WS_CHILD, 90, 110, 75,25, hwndMain, 0, hInst, NULL);

  hwndButton3 = CreateWindow("Button","Acerca de", WS_VISIBLE | WS_CHILD, 190, 110, 75,25, hwndMain, 0, hInst, NULL);

  ShowWindow(hwndMain, nCmdShow);

  while (GetMessageA(&msg, NULL,0,0)) {
   
TranslateMessage(&msg);
    DispatchMessageA(&msg);
  }
  return msg.wParam;
}

Seguimos con las herramientas. Nuestro arsenal personal debe estar compuesto básicamente de:

  • un desensamblador
  • un depurador
  • un editor hexadecimal

El desensamblador es una herramienta que, como su nombre indica, desensambla un programa, o sea, nos muestra su código ensamblador de modo que nosotros podamos estudiarlo. Particularmente yo uso el W32Dasm.

El depurador (o debugger) es una herramienta que nos permite no sólo desensamblar un programa, sino también correrlo, ponerle breakpoints en determinadas posiciones del código, efectuar cambios en el código cargado en memoria, observar los valores de los registros, la pila; todo al mismo tiempo que lo corremos. Como debugger uso y recomiendo el OlyDbg.

El editor hexadecimal nos permite ver el código en sus valores hexadecimales, además de hacer cambios en ellos para luego guardarlos en disco. Yo uso WinHex.

Y ahora que nuestras armas han sido introducidas procedemos a utilizarlas.

Conociendo al enemigo::

Si ejecutamos nuestro conejillo de indias nos encontraremos con dos cajas de texto y tres botones; los textos para el nombre y el serial, un botón para registrar el programa, otro para cancelar y el último para los créditos del programa.

Como si fuéramos dueños de la situación, enviamos el foco del teclado a las cajas de texto, tecleamos nombre de usuario "yo", serial "1234567890", y le damos al botón Registrar. Tal como sospechamos, el programa no se intimidó ante la confianza que mostramos, pues nos ha dado un mensaje de error con el texto "Los datos no son correctos". Muchos pensarán que este texto no les sirve de mucho.

Entonces procedemos a desensamblar el programa con el desensamblador, a ver qué encontramos de interés. Lo que aparece es una cantidad de código impresionante, mucho más de lo que hemos escrito en C. Entre tantas líneas en ASM sería una locura encontrar la instrucción específica de la condicional que buscamos. Pues que no cunda el pánico, en el menú superior del W32Dasm hay un botón llamado StrnRef.

Botón StrnRef

Si pulsamos en él nos mostrará una ventana con una lista de mensajes, que no son más que todas las referencias de strings que usa el programa; es decir, todas las cadenas de caracteres que aparezcan en el programa se encontrarán allí. Si damos doble clic sobre una de ellas, nos lleva exactamente a la instrucción donde se le hizo referencia. Si se hace referencia al mismo texto en más de una instrucción, por cada vez que se la haga doble clic irá saltando a la siguiente referencia. Ahora vemos que aquel texto de error no era tan inservible. Busquemos el texto; no es tan difícil encontrarlo ya que la lista está ordenada alfabéticamente.

Lista de cadenas de texto.

Una vez localizado, hacemos doble clic para que nos lleve directamente a la instrucción que la referenció y vamos a parar directamente a la dirección 0040135Ch dentro del código, la cual corresponde a una instrucción PUSH, que estaba metiendo en la pila la dirección de memoria que contenía el texto. En el desensamblador que usen verán que cada instrucción corresponde con una dirección en el código; ésta se encuentra al extremo izquierdo con formato 00000000h (la h del final es para saber que el número está en hexadecimal). Normalmente, el código de las aplicaciones Win32 comienza en 00400000h. La segunda columna nos muestra los valores hexadecimales del código, y la tercera el código como tal en ASM.

Importante saber que cada instrucción en ASM tiene un equivalente en hexadecimal, por ejemplo, la instrucción PUSH EBX siempre será 51h, es decir, 51 en hexadecimal.

Si somos lo suficientemente curiosos para seguir explorando las referencias de strings encontraremos otra muy interesante, "Serial correcto, felicidades". Si le damos doble clic, iremos a parar a 00401343h, sólo a unas pocas instrucciones más arriba que la referencia al texto de error. ¿Qué me dice todo esto?: que estamos en la zona caliente. Comencemos a rastrear hacia atrás a partir de las referencias y casi inmediatamente en la posición 0040133Ah encontramos una instrucción JNE, ¡bingo!, sin analizarla podría apostar por ella, no obstante, mejor estar seguro.

Hallando la condicional JNE

La instrucción dice JNE 00401355, es decir, que si una determinada condición no se cumple salte a la dirección 00401335h; luego, si buscamos esta nueva posición veremos que queda exactamente atrás del mensaje de registro satisfactorio. En pocas palabras, si la condición no se cumple salta el mensaje bueno y ve al mensaje malo, de lo contrario muestra el mensaje bueno. Ahora, para ver esta situación mucho más de cerca, copiemos la dirección de la condicional, 0040133A, abrimos el depurador OlyDbg y cargamos el programa allí. Una vez ejecutado veremos la pantalla dividida en varias áreas, donde arriba a la izquierda se encuentra el código ASM. Si allí hacemos click derecho, menú "Go To", submenú "Expression" y nos aparecerá un cuadro de diálogo. Allí ponemos la dirección de la instrucción JNE, 0040133A, damos OK y nos envía directamente a la instrucción deseada.

Instrucción 0040133A en el depurador OlyDbg.

Ahora vamos a analizar el código con detenimiento.

00401338 |. 85C0          TEST EAX,EAX
0040133A |. 75 19         JNZ SHORT 00401355
0040133C |. 6A 40         PUSH 40
; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040133E |. 68 EDA04000   PUSH 0040A0ED
; |Title = "Registro oK"
00401343 |. 68 CFA04000   PUSH 0040A0CF
; |Text = "Serial correcto, felicidades."
00401348 |. FF35 C8C64000 PUSH DWORD PTR DS:[40C6C8]
; |hOwner = NULL
0040134E |. E8 BB800000   CALL JMP.&USER32.MessageBoxA
; \MessageBoxA
00401353 |. EB 4E         JMP SHORT 004013A3
00401355 |> 6A 10         PUSH 10
; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401357 |. 68 15A14000   PUSH 0040A115
; |Title = "Error"
0040135C |. 68 F9A04000   PUSH 0040A0F9
; |Text = "Los datos no son correctos."
00401361 |. FF35 C8C64000 PUSH DWORD PTR DS:[40C6C8]
; |hOwner = NULL
00401367 |. E8 A2800000   CALL JMP.&USER32.MessageBoxA
; \MessageBoxA

Para que no se pierda nadie, a los que no sepan ASM aún les recuerdo que JNZ es exactamente lo mismo que JNE, de hecho ambos se codifican como 75h, al igual que JE y JZ se codifican ambos como 74h.

Aquí vemos que al llegar a JNZ, en caso que la condicional resulte 1 salta a 00401355h y muestra el mensaje de error; de lo contrario, si resulta 0, continúa la ejecución sin saltar, hace lo que nos interesa y llega a un JMP en 00401353h que se asegura de no ejecutar el mensaje de error después de mostrar el de serial correcto (JMP: jump, salta a una dirección del código).

Ahora posicionémonos sobre la instrucción TEST EAX,EAX en OlyDbg y presionemos F2; con ello pondremos un breakpoint en ese lugar. Luego presionemos F9, el programa se abrirá y nos mostrará el diálogo para introducir los datos. Una vez más llenamos las cajas de texto con cualquier cosa, démosle a Registrar y el programa se detiene justo en el breakpoint, debido a que la ejecución ha llegado a esa instrucción del código. Ahora, para ir corriendo el programa de instrucción en instrucción vamos presionando F8. Aquí veremos detalladamente cómo al llegar al JNZ salta a 401355h, justo lo que no queremos que haga.

Carguemos nuevamente el programa; en OlyDbg tienes un botón en la esquina superior izquierda con dos flechas "<<" que nos permite resetear la ejecución. Una vez más nos dirigimos a la instrucción en cuestión, pero ahora vamos a hacer unos cambios en los códigos antes de ejecutar el programa. Haciendo doble clic en una instrucción te permitirá editarla; es importante saber que estos cambios se realizan en memoria, no en disco. Cambiemos JNZ SHORT 00401355 por JZ SHORT 00401355 y presionemos el botón Assemble, tecleemos F9 e introduzcamos cualquier texto en ambos campos, ¡voilá!, ya está: el programa ha aceptado el serial.

Para finalizar, lo único que nos queda es llevar los cambios al disco. Esto lo haremos con el editor hexadecimal. Primeramente retornemos al W32Dasm y posicionémonos sobre la instrucción que nos interesa cambiar (el JNZ). Si miramos abajo, en la barra de estado, podremos ver el offset de la instrucción (en este caso 93Ah, los ceros a la izquierda no cuentan).

Offset de la instrucción 93Ah

Abrimos el WinHex. En él cargamos el programa, en el menú principal vamos a Position » Go To Offset y escribimos 93A, presionamos OK, y nos lleva directo a un número 75 entre todo ese código.

Ubicación de la instrucción en el editor hexadecimal WinHex.

¿Pues qué estamos esperando? Cambia el 75 por un 74 y guarda los cambios en File » Save. Luego abre el programa, introdúcele cualquier cosa y dale Registrar. Ya lo tenemos, el programa está parcheado.

Con todo esto lo que hemos logrado es cambiar el código del programa para que haga lo que nosotros queramos, no lo que su programador le ordenó hacer. Me gustaría decir que aquí teníamos otras opciones además del método "74/75"; podríamos haber sustituido la instrucción JNZ SHORT 00401355 por NOP NOP. Esto vendría a ser otra técnica: "nopear". Con los NOP le decimos al microprocesador que no haga nada, que pase a la siguiente instrucción; de este modo lograríamos que el programa se registrara incluso aunque se escribiera el serial correcto. En este caso habría que cambiar dos números del hexadecimal y sustituirlos por 90 90, que corresponde a decir NOP NOP en ASM.

Tal como mencioné al inicio, esta es una técnica elemental; un buen cracker nunca tratará de cambiar el código del programa que está trabajando. En vez de eso, el trabajo más fino consiste en buscar la parte del código que genera el serial, o sea, la función GetSerial(), analizarla, estudiarla y entenderla para luego hacer un programa que haga todo lo que ésta hace, es decir, un keygen o keymaker. Aun así, parchear a veces se vuelve necesario cuando la función GetSerial() está demasiado protegida o complicada.

Este es el escenario más sencillo que podemos encontrarnos. Aun así, es bastante común. La mayoría de los programadores no le prestan atención a la seguridad de sus productos a la hora de protegerlos. De cualquier forma, cuando te detienes a parchear un programa puedes encontrar cualquier cosa: algunos están protegidos con algoritmos de compactación (yo siempre uso UPX para hacerlos pequeños, más que por protegerlos), lo cual podría ser un problema si eres principiante; otros programas hacen cálculos al iniciarse para verificar que su código no ha sido cambiado (esto creo que me lo encontré en el mIRC), en fin, los modos de protegerse son muchos. Sin embargo, nunca faltarán esos programadores que de ingeniería inversa no han oído hablar absolutamente nada.

Por otra parte, en ocasiones aunque el programa no esté protegido, te podrá ser muy difícil rastrear el código hasta la condicional correcta. A veces hay que tener mucha paciencia y sentarse algunas horas a leer el ensamblador para comprender dónde está la condicional que buscamos. La complicación puede tener dos causas: o el programador tuvo siempre muy clara la idea de la ingeniería inversa o simplemente fue muy desordenado al escribir su código. Pues sí, las chapucerías en lenguajes de alto nivel resultan en grandes cantidades inservibles de códigos ASM.

Respecto a los programas que sólo te piden el serial, ¿no te imaginas la condicional?

if ( Serial_Entrado == "MI-SE-RI-AL" ) {
/* ... */
}

Busca en las referencias de strings del W32Dasm; cuando encuentres un texto que parezca un serial se lo pones al programa y ¡listo!. Las aplicaciones que "hardcodean" el serial son difíciles de encontrar; esto podría darte una idea de cómo quebrantar la seguridad del programa que hizo tu vecino y que te pide un password.

Para los que piensen que estos conocimientos sólo son útiles para quebrantar sistemas de verificación de números de serie, hace un año, mientras cursaba el tercero de informática, decidieron que las prácticas se harían en la escuela. La idea era poner a todos los estudiantes a llenar una base de datos de un censo. El trabajo se efectuaba desde un programa cliente que se encontraba en todas las computadoras y en él se llenaban los formularios de datos. La tarea era realmente desagradable y tediosa y, para mayor fastidio, había que entrar al sistema con una cuenta propia de la cual quedaba un log de quién trabajó y quién no en el servidor. Los alumnos obviamente tenían cuentas limitadas, mientras los profesores tenían cuentas más abiertas que permitían hacer cambios en los logs y otras cosas. Para no aburrir, usuario/serial, usuario/contraseña, ¿cuál es la diferencia?, si tu contraseña es correcta, ¿no depende de una condicional?. Mientras todos en mi escuela sufrieron meses de trabajo inhumano con este censo, yo solo trabajé un día: el primero; al final, para mi sorpresa, salí destacado, pues mis logs mostraban un trabajo infatigable, digno de reconocimientos.

Como verán, el empleo de esta técnica no está limitado a seriales. En cuanto tenga otra tarde libre escribo más sobre técnicas de ingeniería inversa.

Para saber más...

Continuar leyendo

Visual Studio 2005 y su TableAdapter

Krlo [blackhat4all@gmail.com]

El trabajo con bases de datos es el pan de cada día para muchos de nosotros. Existen varias formas de hacerlo en dependencia de la plataforma en que estén montados nuestros datos y las herramientas que usemos para manipularlos. No me quedan dudas de que .NET brinda facilidades extraordinarias a la hora de trabajar.

En el Visual Studio 2005 apareció una herramienta llamada DataSet tipado (o con declaraciones de tipo), hereda directamente del anterior System.Data.DataSet, pero ahora las tablas con las que se conectan son tipos presentes en propiedades del DataSet. Vamos a verlo más despacio.

Insertar un DataSet en nuestro proyecto::

Luego de haber creado un proyecto (en mi caso una aplicación de consola en C#), vamos a agregarle un nuevo elemento. Tal y como aparece en la figura, seleccionamos DataSet.

Agregar nuevo elemento...

Al momento nos aparece en vista de diseño el espacio de trabajo del DataSet. Podemos agregarle desde la Caja de herramienta (ToolBox) un TableAdapter, que es el arroz con pollo de este trabajo. El mismo, como su nombre nos indica, es el encargado de adaptar la información de la base de datos a .NET. Ahora tenemos que configurarlo mediante un wizard (igual lo podemos hacer a mano). Estos son los pasos:

  1. Establecer la conexión a los datos. Para ello necesitamos el Connection String igual al que usamos al construir un objeto SqlConnection. Recordemos que tiene la forma: Data Source=<MiServidor>; Initial Catalog=<MiBaseDatos>; Integrated Security=True. También podemos configurar una nueva conexión y hacerlo pasito a pasito. Visual Studio en cualquier momento programa por nosotros.
  2. Luego definimos la manera en que el TableAdapter se conecta con la DB. Vamos a probar con sentencias SQL; de otra forma habría que hacerlo con procedimientos almacenados o creando unos nuevos.
  3. Ahora necesitamos definir cómo trabajan las sentencias anteriores. Primero seleccionamos dónde está la flecha roja para especificar todos los campos marcados, como aparece en la figura siguiente. En la flecha azul construiremos la consulta.


  4. Asistente de configuración del TableAdapter.

  5. La consulta pudiera ser SELECT * FROM TABLA_X;. Es importante incluir los campos llaves de la tabla si queremos poder actualizar los datos de la base de datos cuando los modifiquemos en tiempo de ejecución.
  6. El próximo paso, ya casi al terminar, es especificar los métodos que queremos que tenga nuestro TableAdapter. Incluya ambos: Fill() y Update(). Después nos mostrará los resultados del asistente y ya estaremos listos para trabajar con el DataAdapter.

Tabla "Alerta" con su adaptador.

Al concluir el wizard podremos tener un objeto como el que aparece en nuestra figura. "Alerta" sería el DataTable que referencia a la tabla dentro de mi base de datos. AlertaTableAdapter nos queda claro lo que es.

Para poder usar nuestros objetos debemos incluir el namespace DataSet1TableAdapters, ubicado dentro del namespace actual de nuestro proyecto. Si trabajamos en una aplicación Windows, nos aparecerá en el Toolbox de la vista de diseño y sólo tendremos que incluirlo y nombrarlo. Seguimos con la vía anterior:

AlertaTableAdapter alerta = new AlertaTableAdapter() ;
DataSet1.AlertaDataTable tabla = new DataSet1.AlertaDataTable() ;
alerta.Fill(tabla) ;

En estos momentos acabamos de llenar la tabla de tipo AlertaDataTable con los datos correspondientes de ejecutar la consulta SQL definida anteriormente. El objeto tabla tiene propiedades muy interesantes como Rows que devuelve una colección con todas las filas de la misma. Podemos indexar de la forma tabla[3][6] y de esta forma acceder a cualquier elemento. De más está decir que tiene métodos para buscar, insertar, y eliminar elementos de la tabla. Es sin duda una forma práctica de trabajar con estos datos.

La mejor parte es que cuando terminemos de trabajar con la tabla, podemos guardar todos sus cambios.

alerta.Update(tabla) ;

Conclusiones::

Hemos visto lo fácil que podemos hacer una conexión a una base de datos, y muy por arriba todas las ventajas que brinda manipular esos datos como objetos. Mediante la utilización de objetos DataSet con declaración de tipos, disponemos de una manera fácil y eficaz de actualizar una base de datos utilizando el modo desconectado que nos dispensa ADO.NET. Espero que el artículo haya sido de su interés, sobre todo, para los nuevos usuarios que están comenzando con el diseño de aplicaciones de bases de datos utilizando Visual Basic 2005.

Continuar leyendo

Delegados en C#

Krlo [blackhat4all@gmail.com]

Los delegados son una herramienta de gran utilidad en .NET. Aunque son usados sólo en casos muy específicos, conocerlos es una gran habilidad de nuestro lado que nos permitirá resolver muchos problemas en el futuro. Para los programadores de C++, el concepto es muy similar al de los punteros a funciones; los programadores de JavaScript tienen una funcionalidad parecida a través de objetos Function (que rara vez se utilizan). La tecnología .NET convirtió esta idea en una herramienta tan fácil de utilizar que es un pecado darle de largo.

Primero que todo vamos a definir qué son los delegados:

Los delegados son un tipo (una clase que, por tanto, ha de ser instanciada para utilizar) encargados de agrupar funciones con una signatura en común. Observe que dice "funciones", pues un delegado puede representar a varias funciones al mismo tiempo.

¿Cuál es el objetivo de un delegado?

El delegado puede ser llamado como una función con la idea de ejecutar, en el mismo orden en que entraron, todas sus funciones asignadas. Ésta es su principal funcionalidad, aunque también veo útil el que nos permita pasar funciones como parámetros a otras funciones. Podremos ver un ejemplo de esto más adelante.

Cómo declarar un delegado::

La siguiente instrucción declara un delegado:

delegate void Compara(int valor, int valor2) ;

El delegado anterior funciona como una clase de nombre "Compara". Esta clase puede contener cualquier función que acepte dos parámetros de tipo int y no retorne nada (void). Cualquier función con esta característica podrá ser agregada al delegado Compara.

Vamos ahora a instanciar delegados de este tipo y asignarle alguna función. Primero definimos dos funciones para utilizar con el delegado. La primera escribe por consola true si el primer valor es menor que el segundo, y la otra función hace exactamente lo contrario.

static void Metodo1(int valor, int valor2){
bool comp = valor < valor2 ;
Console.WriteLine(comp.ToString()) ;
}
static void Metodo2(int valor, int valor2){
bool comp = valor > valor2;
Console.WriteLine(comp.ToString());
}

Ahora instanciemos un objeto de tipo Compara y asignémosle estas funciones:

Compara c = new Compara(Metodo1) ;
c += Metodo2 ;
c(12, 4) ;

Queda bastante claro cómo el nuevo objeto c tiene asignada dos funciones: Método1 y Metodo2. Observar cómo se le agregó el Metodo2 usando el operador +=; esta estrategia es válida para agregarle más funciones al delegado, hasta cansarnos.

La salida por pantalla es:

False
True

Un ejemplo más fuerte::

Este ejemplo, aunque no es muy práctico, transmite la idea de cómo usar delegados para pasar funciones en los parámetros de otras funciones. Tenemos las siguientes funciones que pintan líneas de un punto a otro. Cada una lo hace de forma diferente.

void LineaPuntos(Point uno, Point dos){…} // pinta la línea con puntos equidistantes.
void LineaContinua(Point uno, Point dos){…}
// pinta la línea de forma continua.
void LineaAsterisco(Point uno, Point dos){…}
//pinta la línea con asteriscos equidistantes.

Ahora tenemos otros métodos que dibujan figuras. En el caso del cuadrado traza desde cada uno de sus puntos una línea al siguiente. El triángulo se dibuja de igual manera, al igual que un rombo, un rectángulo y cualquier otra figura que se nos ocurra. Un círculo lo podemos simular con líneas pequeñas, por ejemplo.

El problema llega cuando queremos tener la posibilidad de en tiempo de ejecución poder decidir qué figura dibujar y cómo queremos que dibuje sus líneas. Un método DibujaCuadrado para cada uno de los tipos de líneas no es eficiente. Pues si son n tipos de líneas y m tipos de figuras serían n*m métodos. Podríamos también tener un parámetro tipo_línea y, en dependencia de éste, el método DibujaCuadrado decide como dibujar la figura; pero está la situación de que alguien redescubra (nos llegue en una DLL) una forma de pintar líneas con ceros o con signos diferentes, y tendríamos nuevamente que modificar a DibujaCuadrado... definitivamente muy chapucero. Este es el código del método DibujaCuadrado usando un delegado del tipo Pintor.

delegate void Pintor(Point p, Point p2); //dibuja una línea de p a p2.
public void DibujaCuadrado(Point inicial, int lado, Pintor p){
Point A = inicial;
Point B = new Point(inicial.x, inicial.y+lado);
Point C = new Point(inicial.x + lado, inicial.y + lado);
Point D = new Point(inicial.x + lado, inicial.y) ;
p(A, B) ;
p(B, C) ;
p(C, D) ;
p(D, A) ;
}

Ahora podemos dibujar de una manera cómoda un cuadrado usando cualquier tipo de formato de líneas. Sólo tenemos que implementar los métodos LineaPuntos, LineaContinua y LineaAsterisco y asignárselo a nuestro gusto a un objeto de tipo Pintor; este objeto se lo pasamos a DibujaCuadrado y listo.

Conclusiones::

Ventajas de usar delegados:

  1. Los delegados son similares a los punteros a función de C++, pero poseen seguridad de tipos.
  2. Los delegados permiten pasar los métodos como parámetros.
  3. Los delegados pueden utilizarse para definir métodos de devolución de llamada.
  4. Los delegados pueden encadenarse; por ejemplo, se puede llamar a varios métodos en un solo evento.
  5. No es necesario que los métodos coincidan exactamente con la firma de delegado.
  6. La versión 2.0 de C# introduce el concepto de métodos anónimos, que permiten pasar bloques de código como parámetros en lugar de utilizar métodos definidos independientemente.

Los delegados se usan para implementar los eventos en .NET. Todos los botones tienen un delegado llamado Click de tipo EventHandler (este es el delegado como tal, instanciado dentro de la clase Button). Cuando queremos asignarle funconalidad a miBoton le asignamos un método a su delegado de la siguiente manera:

this.miBoton.Click += new System.EventHandler(this. miBoton_Click);

¿Nunca les ha pasado que borran un el método _Click y al compilar les da error en la línea anterior? Es que ese método estaba asignado a un delegado. Pueden borrar la línea con confianza.

Para saber más...

Continuar leyendo

Un método para actualizar la BIOS

Jorge González Herrera [jorgel.gonzalez@infomed.sld.cu]

Hace cuestión de unos días estaba leyendo unos artículos sobre cómo resetear la contraseña de la BIOS en esta misma revista. Después me puse a meditar y conseguí evaluar de buena idea hablar más sobre el tema de la BIOS, como por ejemplo: su actualización. Para los que no están diestro en la materia, la BIOS de un ordenador no es más que un programa que actúa a bajo nivel con el hardware de la máquina. Me refiero con "a bajo nivel" a que al encenderse la máquina el microprocesador envía una cadena de datos a la BIOS pasándole algunas informaciones sobre su funcionamiento, por ejemplo, su marca, su frecuencia de reloj, entre otros factores.

Para ya finalizar y entrar en tema con esto de "actualizar la BIOS" es bueno decir también que, físicamente, la BIOS es una memoria de tipo ROM, no volátil (cuando se apaga la PC no se pierde la información configurada en dicho programa) y usualmente de tipo flash, es decir, que permite rescribir sobre dicha memoria o "actualizar la BIOS" en este caso. Espero que no tengan una máquina tan vieja como para que la ROM no sea flash ;)

Bueno, antes de empezar les diré que no siempre es necesario la actualización; sólo debemos actualizar dicho programa cuando estamos en presencia de alguna de estas situaciones:

  1. Cambiamos el microprocesador y no es detectado correctamente.
  2. Sin hacer overclock, el sistema no detecta el FSB (bus que conecta el microprocesador con la tarjeta madre) correctamente.
  3. Adquirimos un disco duro actual de una capacidad determinada que no es soportada.

A grandes rasgos, estos son los problemas principales que al menos yo he visto; no queda margen para la duda de que hay muchos más problemas que exigen una actualización rápida de la BIOS y que, lógicamente, tienen que ver con el hardware instalado en la máquina.

Veremos qué hacer para actualizar este programilla. Hay que tener presente que se debe actualizar en condiciones perfectas diría yo, pues por cualquier desliz no quedaría más remedio que tirar la tarjeta madre a la basura. Me refiero a condiciones como: el trabajo con UPS para prevenir fallos con la corriente, disquetes nuevos y una buena torre de disquete; en caso de que esté mala recomiendo pedir una prestada, cepillarse bien los dientes antes de empezar ;) una broma nunca viene mal.

Ya con los dos disquetes necesarios en mano, a uno le hacemos un disco de inicio con MS-DOS y al otro le ponemos la actualización correspondiente. Para obtener dicha actualización hay que saber el fabricante de nuestra tarjeta madre y el modelo (al arrancar la máquina podemos ver esos datos en la parte superior de la pantalla, algo así como: Award Modular BIOS v6.00PG Energy Star Ally); también debemos conocer la fecha y la versión de nuestro BIOS, lo cual podemos ver en la parte inferior de la misma pantalla. Se debe tomar nota de todos estos datos de nuestra BIOS y luego ir a la web de el fabricante, en este caso Award Modular, y ver si en la sección de actualizaciones hay una versión posterior a la que tenemos. Casi siempre se trata de un fichero comprimido, compuesto por varios archivos, uno de los cuales es un ejecutable, otro es de extensión .bin (realmente ese es el nuevo contenido que pasará a la ROM de la BIOS), y el otro es un texto plano, usualmente de tipo .txt. Ahora descomprimimos dicho archivo en el disquete que recomiendo que debe ser formateado, aunque sea nuevo.

Una vez con los dos disquetes en mano, el de inicio (puede ser Windows 95, 98, o cualquier otro sistema operativo) y el otro con la actualización de la BIOS, pasaremos a arrancar desde el disco de inicio. Luego, dentro del sistema introduciremos el de la actualización. Normalmente el comando que se debe escribir es: archivo.exe archivo.bin /opciones. Hay opciones de actualización que son necesarias poner y otras que no; el fabricante nos lo dirá en la web o en el archivo de texto. Ya terminado este proceso hay que reiniciar el sistema, entrar a la BIOS y cargar las opciones por defecto ("Load Optimized Defaults").

Nota: Para realizar esto es necesario tener algunos conocimientos básicos de MS-DOS, en caso de que el proceso de actualización sea realizado bajo ese sistema operativo.

Para saber más...

Continuar leyendo

Reducir riesgos de contaminación

Chacal [mariav.hedez@infomed.sld.cu]

Las últimas generaciones de virus que se transmiten a través del correo electrónico se basan en los dos siguientes requisitos para infectar a la víctima:

  • Se debe abrir el correo electrónico que contiene el virus. Basta con abrirlo, sin hacer clic ni ejecutar nada más.
  • Se debe tener activa una conexión a Internet.

Las dos siguientes medidas profilácticas restringirán en buena medida la posibilidad de los virus de infectar a la víctima por medio de este canal.

En primer lugar, como ya sabe perfectamente, nunca debe abrir mensajes de desconocidos con asuntos que suenen a publicidad, spam o vengan en idioma inglés. Sin embargo, si tiene activada la previsualización de mensajes, estos se abrirán de manera automática en el panel de vista previa sin consultarle antes. Debe, por tanto, desactivar esta característica de la siguiente forma:

Netscape Messenger:
Puede hacer que se muestre/oculte la ventana de previsualización de mensajes en Ver » Mostrar » Mensaje. Alternativamente, puede pulsar una pequeña barra horizontal con dos pequeñas flechas en los extremos, sobre el marco que separa la ventana con la lista de mensajes de la ventana de previsualización, para mostrar/ocultar ésta.

Outlook Express:
En Ver » Diseño, bajo el panel Vista previa, puede activar/desactivar la previsualización de mensajes. Si activa el panel de vista previa, puede configurar la disposición con la cual quiere que aparezcan los mensajes. En segundo lugar, conviene que siempre lea los mensajes desconectado. Es decir, utilice su conexión a Internet exclusivamente para descargar los mensajes a su carpeta de entrada. Una vez recibidos, comience a trabajar sin conexión y entonces los léalos tranquilamente.

Messenger:
Una vez enviados y recibidos los mensajes, seleccione Archivo » Desconectar » Trabajar desconectado.

Outlook Express:
Después de recibir su correo, seleccione Archivo » Trabajar sin conexión. Y recuerde, la mejor protección contra los virus es siempre un buen antivirus. Estos trucos no le protegen de su amenaza, solamente ayudan a reducir ligeramente el riesgo de infección.

Continuar leyendo

Cuba, Internet y desarrollo

José Luis Aparicio

No soy experto en el tema de las redes, servidores u otro tipo de acciones que tengan que ver con la administración de un nodo o proveedor de acceso a la web y correo electrónico, pero en mi posición de usuario de nuestro dominio .cu y en vista de uno de los artículos publicados en esta revista la semana pasada, me he propuesto realizar estas reflexiones.

Nuestro país llegó a Internet muy tarde, en relación a la prontitud con que lo hicieron muchas otras naciones. Desde el principio se ha tratado de avanzar de alguna forma y se puede decir que algo hemos logrado. El pilar de los esfuerzos: Infomed, la "gigante" cubana de salud, laureada en el año 2002 por el premio Stockholm Challenge.

Y es esta Red la que según mis creencias proporciona la mayor cantidad de servicio de correos electrónicos y conexiones en nuestro país. El objetivo: los médicos y el desarrollo de cada uno de ellos. Es verdad que ofrece miles de sitios de Internet sobre medicina y galerías y museos del mundo, además del dominio .cu, pero limita tanto que en verdad llega a ser casi imposible navegar como el "Dios Internet" manda.

Lo primero es lo primero: la conexión. Me siento como un afortunado de contar con mis 25 horas al mes, y digo afortunado porque conozco personas que sólo cuentan con 15, e incluso menos. También puedo decir que puedo mantener la conexión por tiempo ilimitado, mientras que a otras personas se les cae la red pasados 45 minutos, sin importar lo que esté haciendo. Pero aunque debiera sentirme de alguna manera feliz, no me conformo con esto, sabiendo que en otros países, gracias a la anhelada banda ancha, tienen conexión las 24 horas con velocidades extraordinarias.

Todo esto se siente al tener que realizar un download o descarga, ya que lo que por un módem a 56 Kbps nos puede quitar 4 horas, por una conexión banda ancha a 512 Kbps nos llevaría sólo 2 minutos. Eso es sin mentir, obviando que hay conexiones de más velocidad. Analicen y verán que no contamos ni con una hora para cada día de un mes promedio de 30 jornadas. No pido la fibra óptica, más barata y eficiente, pero se podría lograr algo comprando más servidores.

Lo otro es el correo electrónico, uno de los servicios imprescindibles para todos. El e-mail de Infomed es quizás de los peores del mundo. Demora años para recibir correos, más con adjuntos, y estos no pueden alcanzar grandes cantidades. ¿A quién no le ha rebotado más de una vez un correo porque se pasa de límite, demostrando que la capacidad es ínfima?

Pero el espectáculo mayor de la mensajería son las roturas olímpicas de las que sufre. Casi un mes entero sin e-mail pasamos los usuarios del correo electrónico del nodo de Infomed en Villa Clara, nuestro problemático Capiro. Y es que el viejo servidor no soportó un día de lluvias y "voló como una cafetera", citando palabras textuales del administrador local de dicha red. Solución: esperar a que dieran el dinero para arreglarlo o comprar uno nuevo. Después, la clásica falta de recursos y el tardío remedio del problema; nada, que aunque es nuevo y tiene un mes de estreno, sólo la madre naturaleza deja escapar sus gotas y ¡pum!, sin correo hasta el otro día.

Y es que no pedimos un Gmail o un Yahoo!, pero tampoco un método que nos recuerda al utilizado por aquella ARPANet a principios de los años '70.

Las limitaciones a páginas internacionales son otras de las dificultades que afronta la Red Telemática de Salud. Las páginas a las que se puede acceder son de salud o de museos del mundo, como se había referido anteriormente. Otras a las que se brinda acceso son a las de empresas o corporaciones de la informática que, lejos de instruir, lo que hacen es que comprendamos que hay que poner dinero de por medio para conseguir lo brindado. No va a hacerle nada a nadie que autoricen un par de sitios de descargas, noticias, etc. Eso, lejos de cambiar idealizaciones, lo que hace es ampliar conocimientos y cultura.

Si queremos tener un país culto y desarrollado debemos contar con Internet, el medio principal de difusión y de información del mundo actual. Se conoce que la red de redes alberga contenido ilícito, pero con un buen control de los sitios que se puedan visitar se podría lograr una navegación con todas las de la ley.

Creo que lo primero es tomar iniciativas para ver si logramos mejoría. Podríamos crear un buzón de e-mails y alertar a los usuarios de Infomed para crear un documento donde expongamos soluciones y opiniones sobre Infomed, firmado por un gran número de usuarios de esta red y presentarlo a las máximas autoridades de la Red Cubana de Salud.

Es sólo una idea, ya que podría haber otras. Lo que sí debemos tener conciencia y actuar rápido, ya que si la mejor revista de Informática de Cuba -la querida BlackHat- no tiene host, entonces estamos al borde de la Apocalipsis del Internet en Cuba, que lejos de mejorar, empeora cada día.

Para saber más...

Continuar leyendo

FruityLoop Studio 5.0

Alien [blackhat4all@gmail.com]

La informática es un árbol gigante con cientos de ramas. Es un campo que está vinculado con todas las demás esferas y, que además, las ayuda a su desarrollo. Podemos ligarla a las comunicaciones, al diseño grafico, a la modelación de situaciones, e incluso, hasta con la música.

¿Quién no quisiera crear su propia agrupación o dedicarle un CD a una novia? ¿A quién no le gustaría poner en el inicio de sesión un sonido que hace días le ronda en la cabeza o modificar el final de su canción favorita?

Esas son algunas de las preguntas que se pueden contestar con una sola respuesta: FruityLoop Studio 5.0.

¿Qué es?
A mi entender, la más poderosa herramienta con que pueda contar alguien que sea fanático de la música y no haya ido nunca a una escuela de arte. Es similar a tener dentro de la pantalla de su monitor un grupo de música, y qué digo... ¿un grupo?; puede ser una orquesta o mucho más allá: una sinfónica completa o... Nada, que sólo se puede comparar con tener otro FruityLoop.

FL Studio, como quizás algunos lo conocen, es una aplicación perfecta, tanto para máquina lentas como para las más modernas. Imagínense tener cerca de 500 WAV, comprimidos en un instalador de tan sólo 37 Mb, y si añadimos a esto los más de 1600 .fst, sonidos reconocidos sólo por FL Studio y que también podemos utilizar a la hora de crear nuestras propias interpretaciones, podemos entonces contar con una biblioteca de más de 2000 sonidos. Pero Image-Line Software, creadora de tan formidable programa, no se conformó con esto: todos y cada uno de esos sonidos puede ser ecualizado, recortado, alargado, distorsionado, etc., obteniendo como resultado nuevas melodías, que no comprometen al sonido original.

¿Ya se imaginan eso? Bien, ahora les traigo más.

FL Studio cuenta además con una serie de opciones que no tienen nada que envidiarle a un estudio de música profesional (salvando siempre las diferencias entre uno y otro, por supuesto). Este programa cuenta con marcadores para llevar el compás de la música, un contador de tiempo, infinitos patterns donde colocar más melodías; es capaz de grabar audio, incorpora un piano que no se diferencia en nada a los convencionales, una serie de sonidos que nos pueden ayudar a comenzar una interpretación, una ayuda fabulosa, capacidad para hacer música sin limitaciones de tiempo; graba como WAV y como MP3 en distintas calidades, controles de volumen corrección de velocidad... (un momento, déjenme respirar).

Nada, que es todo una discográfica y yo aún no lo he explorado del todo.

Habrá muchos incrédulos que estarán pensando: -pero los sonidos son irreales. ¡Para Nada! A esos que piensan así, los invito a instalar FL Studio en sus casa y hacer la prueba. Cuando lo tengan abierto, naveguen usando el browser que está a la izquierda hasta Cool Stuff, pasando por Projects, allí encontrarán una serie de ejemplos de lo que se puede hacer el FL Studio 5 y luego respóndanme, ¿son esos sonidos irreales?

A diferencia de FL Studio anteriores, esta versión es mucho más fuerte respecto a la calidad del sonido, aparte de tener una mayor cantidad de éstos; la diferencia con los ecos provenientes de instrumentos reales es ínfima.

¿Cuán difícil es?
No les mentiré diciéndoles que es coser y cantar. Al principio, si quieren hacer algo que realmente se pueda escuchar, tendrán que dedicarle varias horas, pasar muchos trabajos antes de poder hacer su primer do-re-mi; sin embargo, tampoco hay que ser graduado de la ENA para hacer un rap digno de ser interpretado por una agrupación de prestigio, o hacer un reggaetón al que se le pueda añadir luego la más sucia letra y hacer que pegue durante algunas semana en los Hit Parade de Piso 6. Todo es cuestión de tiempo.

Habrán algunos que prefieran hacer la música de manera más fácil, y para esto utilicen programas como el Ejay, donde todo está conformado, sólo hay que unir unas cuantas melodías y cajas, y en cuestión de minutos se puede tener un background. FL Studio es distinto, y aunque tiene unos diez sonidos predeterminados con los que se puede trabajar, el objetivo primordial es ser capaz de crear una melodía que se diferencia en todo a las demás. Al utilizar FruityLoop Studio 5.0 nos estaremos asegurando que nadie más ha hecho hasta el momento un sonido como el que hemos creando, nuevo, distinto, limpio y, lo más importante, sin tener nada que envidiarle a los demás.

Pero nada es perfecto y FL Studio 5.0 tampoco lo es. Como dije antes, no me considero un experto en sonidos, pero para mí y para varios amigos que sí saben de música, el único problema hasta ahora es que está en inglés, y aunque no dificulta mucho el aprendizaje (porque casi todo es a base de iconos que fácilmente se pueden entender), sí puede ser un problema para quien no domine las bases del idioma y quiera aprenderse algunos truquito que van más allá de la ayuda.

Pero como dice mi amigo imaginario: "No os preocupéis", para esto está uno de los tutoriales más completos que he visto, y que por suerte viene integrado junto con la instalación del programa (son unos genios, pepito).

Navegando por el browser del Fruity podemos llegar a tutorial luego de haber pasado previamente por Projects, allí no sólo nos enseñan a trabajar, sino que de forma dinámica vemos cómo se van haciendo las cosas, cómo suenan los elementos, nada... que es lo mejor.

¿Requerimientos de Hardware?
¡Ninguno!, FruityLoop Studio 5.0 es un programa que lo único que necesita para funcionar es una tarjeta de sonido. Tanto es así, que hace un tiempo atrás tuve la oportunidad de probar la versión 3.0 en una máquina con 166 MHz de microprocesador, 96 Mb de RAM, 800 Mb de HDD, y como si nada. Quizás un poco lento para abrirse (se demoraba unos 15-20 s), pero una vez que estaba completamente descargado en la RAM, era como estar trabajando en un P4 DualCore (ahora que recuerdo bien, no era tan así). No obstante, en el manual de referencia (que por desgracia viene en inglés) aparecen varias opciones con las que se puede reducir así el consumo de recursos por parte de la aplicación.

La versión 5.0 de FL Studio supera por mucho a las anteriores. Y ya en esta caduca antecesora se podía disfrutar del final de la película "Romeo must die", interpretada por Aaliyah y Jet Lee como protagonistas. En esta nueva y super mejorada versión que nos ha traído Image lline, el emocionado ejemplo no aparece; sin embargo, contamos con una amplia gama de sonidos que lo reemplazan y que perfectamente pueden reemplazar al monótono sonido de Windows.

Las enormes cualidades de FruityLoop Studio 5.0, hacen que sea para mí el programa por preferencia exclusiva a la hora de crear una canción o editar un tema para un video. Sólo por las facilidades que me brinda y la seguridad de que no estoy plagiando otro tema anterior, me hacen concederle el premio al mejor programa de audio con los que he trabajado (y aún no he visto la versión 6, ni la 7).

Para saber más...

Continuar leyendo