Código ensamblador en Visual Basic 6

Tamaño de letra:

Ensamblador en VB6

Tenía guardado en mi disco duro dos ejemplos de cómo ejecutar código ensamblador en Visual Basic 6. Aunque VB6 va poco a poco perdiendo adeptos, antes de borrar estos dos ejemplos prefiero compartirlos y tal vez a alguno todavía le sirva. En este tutorial voy a ejecutar un simple código y mostraré cómo extraerlo usando por ejemplo OllyDBG (v1.10 - v2). En el siguiente artículo que escriba sobre este tema, mostraré otra forma de realizarlo y se podrá observar la velocidad del mismo código en VB6 y en asm.

Para ejecutar código asm en VB6 se suelen utilizar dos alternativas:

  1. Mediante el uso de una herramienta externa (complemento)
  2. Programando "a mano" creando código asm inline (en línea)

Para este primer ejemplo voy a programarlo a mano. El código que tengo guardado es una variante que he hecho, basándome en un código muy sencillo que encontré hace ya unos años en este enlace:
http://foro.elhacker.net/programacion_vb/srcsnippet_tecnica_antidebugging_asmvb_callwindowproc-t244267.0.html. Un código que vamos a adaptar, analizar, explicar y optimizar para que puedas usarlo. Voy a emular la conocidísima API IsDebuggerPresent, que yo creo que no necesita presentación.

Código asm de IsDebuggerPresent

Aunque voy a generar el código asm a mano, yo prefiero (prefería) hacerlo usando un complemento para VB6 que en el siguiente tutorial mostraré, pero esta es una rápida alternativa. Lo único malo es que necesitas los valores en hexadecimal del código ensamblador pero te voy a enseñar cómo obtenerlos en menos de 1 segundo.

Primer paso: obtención del código

Por ejemplo, vamos a programar algo muy sencillo para entenderlo y que nos sea útil. Voy a abrir en OllyDBG (v1.10 o v2) un programa cualquiera. Cuando esté cargado pulso Ctrl+G y voy a poner exactamente IsDebuggerPresent que es una API que comprueba si un debugger está depurando nuestra aplicación. El código que encuentro es el siguiente:

7C813123    64:A1 18000000    mov eax,dword ptr fs:[18]
7C813129    8B40 30           mov eax,dword ptr ds:[eax+30]
7C81312C    0FB640 02         movzx eax,byte ptr ds:[eax+2]
7C813130    C3                retn

Las direcciones 7C81XXXX seguramente no se corresponderán con las tuyas pero da igual. OllyDBG ya muestra todo lo que realmente interesa: las instrucciones y el código hexadecimal. Si al ejecutar IsDebuggerPresent el resultado final de eax es:

  • 0 -> No hay debugger
  • 1 -> Sí hay debugger

Voy a copiar separados por un espacio todos los valores en hexadecimal de las instrucciones:
64 A1 18 00 00 00 8B 40 30 OF B6 40 02 C3 en total 14 bytes.

Obtener el valor hex desde OllyDBG

Como puedes imaginar, si el código fuera extenso, copiar todos los valores te puede llevar trabajo y posibles equivocaciones. Para evitar esto, puedes copiar los datos hex directamente desde OllyDBG:

Binary Copy en OllyDBg

Los números 12 corresponden a OllyDBG 1.10 mientras que los números 34 a OllyDBG 2. Lo primero es seleccionar el código 13 y después pulsar el botón derecho y seleccionar los ítems 24 dependiendo de la versión de Olly.

Generando la subrutina o función en asm

Y ahora ya podemos empezar con el código que usaremos en Visual Basic 6. De forma muy general, lo que voy a hacer es crear una función (o subrutina si quieres, pero como IsDebuggerPresent devuelve 0 o 1 voy a crear un función con resultado booleano) para generar y ejecutar todo el código asm y lo que hará esta función es pegar esos valores hex en memoria uno a uno y después mediante CallWindowProc generaremos un procedimiento para que el código salte a la dirección de comienzo del asm. Vamos a ello. Crearé un esqueleto que te puede servir para tu propio programa.

Crea un nuevo proyecto en VB6, un exe estándar. Dibuja la interfaz como quieras pero añade un botón que será el que ejecute código asm. Yo al formulario lo he llamado "principal" y al botón "btn_ejecutar". La función la voy a llamar asm_IsDebuggerPresent, que voy a insertar en el código general del formulario:

Private Function asm_IsDebuggerPresent() As Boolean
End Function

Ahora crearemos una matriz asm() con todos los valores hexadecimales y la función CallWindowProc. Voy a usar una (constante-1)=bytes_codigo, para crear el array. La función asm_IsDebuggerPresent queda así:

Private Function asm_IsDebuggerPresent() As Boolean
      Dim asm(bytes_codigo) As Byte
      Dim indice As Integer
      Dim codigo_asm, bytes() As String
      codigo_asm = "64 A1 18 00 00 00 8B 40 30 0F B6 40 02 C3"
      bytes = Split(codigo_asm, " ", -1, vbTextCompare)
      For indice = 0 To UBound(asm)
            bytes(indice) = "&H" & bytes(indice) 'Se quedan en Unicode
            asm(indice) = CByte(bytes(indice)) 'Los transforma en bytes
      Next indice
 
      'Ejecutar el código desde el principio VarPtr(asm(0). La función retorna un valor Long
      'por eso le obligo a devolver un valor Booleano y que nos sirva en nuestra función:
      asm_IsDebuggerPresent = CBool(CallWindowProc(VarPtr(asm(0)), 0&, 0&, 0&, 0&))
End Function

Y todo el código final queda así:

'Declaración de la función CallWindowProc:
Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, _
 ByVal hwnd As Long, _
 ByVal msg As Long, _
 ByVal wParam As Long, _
 ByVal lParam As Long) As Long
'Constante con el número exacto de bytes - 1:
Const bytes_codigo = 13
 
'Función que genera y ejecuta el código ensamblador:
Private Function asm_IsDebuggerPresent() As Boolean
      Dim asm(bytes_codigo) As Byte
      Dim indice As Integer
      Dim codigo_asm, bytes() As String
      codigo_asm = "64 A1 18 00 00 00 8B 40 30 0F B6 40 02 C3"
      bytes = Split(codigo_asm, " ", -1, vbTextCompare)
      For indice = 0 To UBound(asm)
            bytes(indice) = "&H" & bytes(indice) 'Se quedan en Unicode
            asm(indice) = CByte(bytes(indice)) 'Los transforma en bytes
      Next indice
 
      'Ejecutar el código desde el principio VarPtr(asm(0). La función retorna un valor Long pero
      'le obligo a devolver un valor Booleano y que nos sirva en nuestra función:
      asm_IsDebuggerPresent = CBool(CallWindowProc(VarPtr(asm(0)), 0&, 0&, 0&, 0&))
End Function
 
Private Sub btn_ejecutar_Click()
      Dim eax As Boolean
      eax = asm_IsDebuggerPresent
      If eax = True Then
            MsgBox "Debugger detectado", vbExclamation, "IsDebuggerPresent"
      Else
            MsgBox "Debugger no detectado", vbInformation, "IsDebuggerPresent"
      End If
End Sub
 

Muy sencillo de entender y optimizado para que lo puedas modificar y utilizar de forma sencilla. Iba a incluir el proyecto y el programa compilado, pero creo que con el código y la explicación basta. Si realmente lo crees necesario coméntalo.

Quiero dar las gracias desde aquí a Karcrack, usuario de elhacker que fue el que realizó el código original (el enlace del principio de este artículo) y que yo he copiado y adaptado.

Última actualización: Martes, 14 Febrero 2012
Comentarios  
0 # cristhoperelsemental 20-08-2019 21:57
:-x :-x :-x :-x :D :lol: :-) ;-) :lol: :-* :-| 8) :oops: :sad: :cry: :o :o :-? :-x :eek: :eek: :zzz :P :P :roll: :sigh:
0 # karmany 21-08-2019 15:03
:-) :-) :-)

No tiene privilegios para responder a los comentarios.


 
Visitas: 8487851