Aplicaciones de consola en VB6
Introducción
Este artículo consiste en aprender a escribir programas de consola en Visual Basic 6. Se verá la forma de crear aplicaciones que corran en modo consola sin mostrar el formulario, se asume 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".
<source lang="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;</source>
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.
<source lang="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.</source>
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
<source lang="vb">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</source>
Constantes
<source lang="vb">Private Const STD_OUTPUT_HANDLE = -11& Private Const FOREGROUND_GREEN = &H2</source>
Código
<source lang="vb">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
' Mostramos el texto en la consola
WriteConsole hConsoleOut, ByVal sTexto, Len(sTexto), lWritten, ByVal 0&
End If
'Matamos la consola
CloseHandle hConsoleOut
FreeConsole
End ' fin de ejecución
End Sub</source>
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, se ha 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.
Editando fichero y cambiando el valor de Subsystem
Ahora abriremos nuestro fichero compilado en un editor hexadecimal, se ha 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.
Salvamos el fichero y ahora lo corremos desde el cmd.exe o command.com. El resultado final es:
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 se podría ya empezar a programar una aplicación en consola
Fuente
Manual "Peering Inside the PE"
Manual Aprenda VB6 como si estuviera en primero