Glitch City Laboratories Archives

Glitch City Laboratories closed on 1 September 2020 (announcement). This is an archived copy of a thread from Glitch City Laboratories Forums.

You can join Glitch City Research Institute to ask questions or discuss current developments.

You may also download the archive of this forum in .tar.gz, .sql.gz, or .sqlite.gz formats.

Programming/Scripting/Development/Web Design

Executing assembly language code in Visual Basic - Page 1

Executing assembly language code in Visual Basic

Posted by: Zowayix
Date: 2013-06-10 13:08:58
(Sure is a lot of Basic-related language threads around here… oh well.)

This isn't a help topic or anything like that, but I figured this is so brilliant and at the same time so completely and utterly stupid that I should post it here to see if anyone else is as crazy as I am.
But it's not all my fault, I took the idea from here:

I took it upon myself to rearrange the code to something I consider a bit less ugly (I'm not sure that other one actually works).

  MultiUse = -1  'True
Attribute VB_Name = "AssemblyHax"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

#If VBA7 = 0 Then
    Private Enum LongPtr
        NULL_PTR = 0
    End Enum
    Private Const NULL_PTR as LongPtr = 0
#End If

Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As LongPtr
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As LongPtr) As BOOL

Private Declare Sub GetMem4 Lib "msvbvm60" (ByVal addr as LongPtr, ByRef out as Long)
Private Declare Sub RtlMoveMemory Lib "kernel32" (dest As Any, src As Any, ByVal length As Long)

Private hMem As LongPtr

Private Function decodeBytes(s As String) As Byte()
    Dim out() As Byte, i As Long
    Dim size As Long
    size = Len(s) \ 2
    ReDim Preserve out(0 To size - 1)
    For i = 1 To size
        out(i - 1) = CByte("&H" & Mid$(s, i * 2 - 1, 2))
    decodeBytes = out
End Function

Private Function getLong(addr as LongPtr) as Long
GetMem4 addr, getLong
End Function

Function dontCallThisFunction(ByRef buf As Byte) As Long
End Function

Function executeASM(ByVal asm As String) As String
    Dim b() As Byte
    b = decodeBytes(asm)
    Dim vTablePtr As LongPtr
    vTablePtr = getLong(ObjPtr(Me))
    Dim memPtr As Long
    hMem = GlobalAlloc(0, Len(asm) \ 2)
    memPtr = GlobalLock(hMem)
    RtlMoveMemory ByVal memPtr, b(0), Len(asm) \ 2
    GlobalUnlock hMem
    RtlMoveMemory ByVal vTablePtr + &H1C, memPtr, 4
    Dim buf(0 To 11) As Byte
    dontCallThisFunction buf(0)
    executeASM = StrConv(buf, vbUnicode)
End Function

Private Sub Class_Terminate()
    If hMem <> NULL_PTR Then GlobalFree hMem
End Sub

Function cpuID() As String
    cpuID = executeASM("578B7C240C33C00FA2891F895704894F085F33C0C3")
End Function

So you basically just create a new instance of AssemblyHax after importing this class, and call its cpuID method. The rest is magic.

Oh, alright. I'll attempt to explain said magic, and why this needs to be a class and not a standard module:
- COM objects (which all VB objects are) use virtual method tables internally
- executeASM first gets this object's actual memory address and dereferences the Long variable there to get the pointer to this v-table
- It then overrides the first function pointer of this v-table (hence it is important that dontCallThisFunction is the very first public function in order of declaration) with some arbitrary byte values, which is stored as a String because it's just easier that way
- Executes dontCallThisFunction which now actually has a method body (with those bytes), passing it a Byte array so it can store the returned values in some registers or however x86 assembly works
- Returns a string saying "GenuineIntel" or whatever

Feel free to throw up after reading this. I don't really blame you.

EDIT: Whoops, I forgot something I had in another module (namely the LongPtr hack) that this was taken from. Won't compile without it, so I put it in the private declarations. And the byteArray function wasn't even used. My stupid.

Re: Executing assembly language code in Visual Basic

Posted by: tachi
Date: 2013-06-10 16:30:34
T.T I haven't used basic since highschool….well wait no…in freshman year in college with the TI 84, but that was just 3 to 4 lines of script…
:( i've forgotten so much…