Escribiendo Aplicaciones de Consola en Visual Basic 6



Seguro muchos de nosotros alguna vez habremos pensado en escribir programas de consola en Visual Basic pero hemos tenido que migrar a lenguajes como C o Pascal por que como su nombre lo indica este lenguaje es “Visual”.


La realidad es distinta y en este post, les mostraré la forma de crear aplicaciones que corran en modo Consola sin mostrar el formulario, asumiré que se tienen los siguientes conocimientos:

  • Visual Basic 6.
  • Uso de las Win32 API’s.
  • PE (Portable Executable) Header.

Herramientas Utilizadas

  • Editor Hexadecimal.
  • PE Editor.
  • Visual Basic 6.

Aplicaciones de Consola y la PE Header.

El formato PE es basicamente una estructura de datos que encapsula la información necesaria para el cargador de Windows para gestionar el código de un ejecutable.

Dentro de un Ejecutable PE, podemos encontrar una estructura que nos servirá para nuestro fin (Crear ejecutables de consola).
La estructura “IMAGE_OPTIONAL_HEADER”.

C:
typedef struct _IMAGE_OPTIONAL_HEADER {
    //
    // Standard fields.
    //

    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;

    //
    // NT additional fields.
    //

    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

De toda esta estructura el único dato que nos interesa es el valor “Subsystem” de 16 bits (2 bytes).
Subsystem puede llevar distintos valores, el valor que contienen las aplicaciones GUI es 2 y las consolas tienen el valor 3.

C:
#define IMAGE_SUBSYSTEM_WINDOWS_GUI          2   // Image runs in the Windows GUI subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_CUI          3   // Image runs in the Windows character subsystem.

Por lo tanto modificaremos el valor de los ejecutables que compilemos en Visual Basic, para ello necesitaremos un editor de archivos PE para ubicar el offset del Subsytem y un editor Hexadecimal para modificarlo.

Creando la aplicación de Consola

Haremos algo sencillo, utilizaremos las APIS para manejar la consola y escribiremos en ella “Hello Override – Algoritmatica has you” y el texto cambiará de color a Verde.

Apis necesarias:

Visual Basic:
Private Declare Function FreeConsole Lib "kernel32" () As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long
Private Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" (ByVal hConsoleOutput As Long, lpBuffer As Any, ByVal nNumberOfCharsToWrite As Long, lpNumberOfCharsWritten As Long, lpReserved As Any) As Long
Private Declare Function SetConsoleTextAttribute Lib "kernel32" (ByVal hConsoleOutput As Long, ByVal wAttributes As Long) As Long
Private Declare Function SetConsoleTitle Lib "kernel32" Alias "SetConsoleTitleA" (ByVal lpConsoleTitle As String) As Long

Constantes

Visual Basic:
Private Const STD_OUTPUT_HANDLE = -11&
Private Const FOREGROUND_GREEN = &H2

Código

Visual Basic:
Private Sub Form_Load()
Form1.Hide ' Ocultamos el formulario
    Dim hConsoleOut As Long
    hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE) ' Obtenemos el handle de la consola
    If (hConsoleOut) Then   
        Dim sTexto As String
        Dim lWritten As Long
        sTexto = "Hello Override - Algorimatica has you!"  ' Texto a mostrar en la consola
        SetConsoleTitle ("Algoritmatica.com")                    ' Cambiamos el titulo de la consola
        SetConsoleTextAttribute hConsoleOut, FOREGROUND_GREEN  ' Cambiamos el color de texto de las letras
        WriteConsole hConsoleOut, ByVal sTexto, Len(sTexto), lWritten, ByVal 0&   ' Mostramos el texto en la consola
    End If
    'Matamos la consola
   
    CloseHandle hConsoleOut
    FreeConsole
    End ' fin de ejecución
End Sub

Compilando Código

Ahora compilamos nuestro código como lo haríamos de manera normal y generamos nuestro ejecutable, en mi caso lo he llamado test2.exe.
Una vez compilado necesitaremos nuestro Editor Pe, en este caso, yo he usado la herramienta “PEview”.

Buscando Subsystem

Abrimos nuestro archivo compilado (Test2.exe) en el Peview y expandemos el árbol “IMAGE_NT_HEADERS” y seleccionamos “IMAGE_OPTIONAL_HEADER” ahora del lado derecho buscamos
“Subsystem” y encontramos que se encuentra en el offset 0x00000114.

PE VIEW

Editando fichero y cambiando el valor de Subsystem

Ahora abriremos nuestro fichero compilado en un editor hexadecimal, yo he usado WinHex.
Buscaremos la offset 0x00000114 y vemos que tiene el valor 0x02, modificaremos el valor y colocaremos 0x03 lo que hará que el ejecutable corra en modo Consola.

Hexadecimal editing
Salvamos el fichero y ahora lo corremos desde el cmd.exe o command.com

El resultado final es:

Ejecutable vb6 en consola

Notas finales

Como nota final, se podría crear una función que escriba en la consola y otra función que espere por entrada de datos algo así como funciones equivalentes en C como son printf y scanf.
Con esas dos funciones podríamos ya empezar a programar nuestra aplicación en consola

digg it
meneame

Guardar / Compartir este Artículo

Del.icio.us StumbleUpon Fresqui Technorati Barrapunto Google

Dejar un comentario

Powered by WP Hashcash