VB6 Hijacking

Author: David Zimmer
Date: 07.04.21 - 5:04pm

So a forum user wanted to devise a way to automate a VB6 application that did not have a plugin or scripting framework. He wanted to get a hold of the Vb.Global.Forms collection so that he could access the open forms and then automate them as if his dll was loaded as a plugin.

Another forum user knew where to find the cached Vb.Global pointer, and the following code ensued: (you can read the fill thread here)

Option Explicit
'add one listbox and two buttons

Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Sub GetMem4 Lib "msvbvm60.dll" (ByVal lAddress As Long, var As Long)
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cBytes&)

Private Type extEntry
    flag As Long
    offset As Long
End Type

Dim readyToReturn As Boolean

Private Sub Command1_Click()
    readyToReturn = True
End Sub

Function IsIde() As Boolean
    On Error GoTo out
    Debug.Print 1 / 0
out: IsIde = Err
End Function

Private Sub Command2_Click()
End Sub

Private Sub Form_Load()

'    Dim v  As VB.Global
'    MsgBox v.App.EXEName 'variable not set..this is good, sanity check
'    End
    If IsIde Then
        MsgBox "Only run compiled"
        Me.Caption = "It worked!"
        Command1.Caption = "Continue"
        Command2.Caption = "End"
        List1.Move 0, 0, 8000, 8000
        Me.Width = 8400
        Me.Height = 9100
        Command1.Move Me.Width - 3000, 8025
        Command2.Move Me.Width - 1500, 8025
    End If
End Sub

Sub xx(msg As String, v As Long, Optional wait As Boolean = False)
    List1.AddItem msg & ": " & Hex(v) & IIf(wait, "  --- Waiting for continue click...", Empty)
    If wait Then
        readyToReturn = False
        While Not readyToReturn
    End If
End Sub

Private Sub DoTheTrickStuff() Dim vbHeader As Long, lpProjectData As Long, projectDataPointerValue As Long Dim lpExternalTable As Long, externalTablePointerValue As Long Dim externalCount As Long, lpExternalCount As Long Dim i As Integer, e As extEntry, myCaption As String Dim globalPtr As Long, lpGlobalPtr As Long, globalClone As VB.Global Me.Visible = True xx "The pointer I am after", ObjPtr(VB.Global) vbHeader = GetVBHeader() xx "Header", vbHeader lpProjectData = vbHeader + &H30 GetMem4 ByVal lpProjectData, projectDataPointerValue xx "lpProject", projectDataPointerValue lpExternalCount = projectDataPointerValue + &H238 xx "lpExternalCount", lpExternalCount GetMem4 ByVal lpExternalCount, externalCount xx "ExtCount", externalCount lpExternalTable = projectDataPointerValue + &H234 xx "lpExtTable", lpExternalTable GetMem4 ByVal lpExternalTable, externalTablePointerValue xx "ExtTable", externalTablePointerValue For i = 0 To externalCount CopyMemory ByVal VarPtr(e), ByVal externalTablePointerValue, 8 Debug.Print i & ") " & Hex(externalTablePointerValue) & " " & e.flag & " " & Hex(e.offset) If e.flag = 6 Then 'Tag of global object xx "Found flag", e.flag GetMem4 ByVal e.offset + 4, lpGlobalPtr xx "lpGlobalPointer", lpGlobalPtr GetMem4 ByVal lpGlobalPtr, globalPtr xx "GlobalPointer", globalPtr If globalPtr = ObjPtr(VB.Global) Then List1.AddItem "Success!!" Else List1.AddItem "FAIL!!" Exit For End If Set globalClone = GlobalFromPointer(ByVal globalPtr) xx "ObjPtr(globalClone)", ObjPtr(globalClone) ', True myCaption = globalClone.Forms(0).Caption List1.AddItem "globalClone.Forms(0).Caption = " & myCaption globalClone.Forms(0).Caption = "Are you sure?!" Exit For End If externalTablePointerValue = externalTablePointerValue + 8 Next List1.AddItem "Complete" End Sub Private Function GlobalFromPointer(ByVal ptr&) As VB.Global ' this function returns a reference to our form class ' dimension an object variable that we can copy the ' passed pointer into Dim globalClone As VB.Global ' use the CopyMemory API function to copy the ' long pointer into the object variable. CopyMemory globalClone, ptr, 4& Set GlobalFromPointer = globalClone CopyMemory ptr&, 0&, 4& End Function Public Function ObjFromPtr(ByVal pObj As Long) As Object Dim obj As Object CopyMemory obj, pObj, LenB(obj) 'not size 4! Set ObjFromPtr = obj CopyMemory obj, 0&, LenB(obj) 'not size 4! End Function ' // Get VBHeader structure Private Function GetVBHeader() As Long Dim ptr As Long Dim hModule As Long hModule = GetModuleHandle(ByVal "Project1.exe") ' Get e_lfanew GetMem4 ByVal hModule + &H3C, ptr ' Get AddressOfEntryPoint GetMem4 ByVal ptr + &H28 + hModule, ptr ' Get VBHeader GetMem4 ByVal ptr + hModule + 1, GetVBHeader End Function Private Sub Form_Resize() On Error Resume Next List1.Width = Me.Width End Sub

Special considerations:
  • inject native dll which loads vb dll as "plugin"
  • native call vb6 activex method which sets timer
  • vb plugin must execute in the same thread as STA main vb6 app


find the VBHeader.aProjectInfo at offset 0x30 of the VBHeader

walk the VBHeader.aProjectInfo.aExternalTable (offset 0x234 in VBHeader.aProjectInfo struct) of which there will be VBHeader.aProjectInfo.ExternalCount entries (offset 0x238 from start of VBHeader.aProjectInfo )

each entry will be an 8 byte structure

private type extEntry flag as long offset as long end type

when you find flag = 6 you found your target. at that target.offset you will find another 8 byte structure

private type extEntryTarget clsidIIDStructOffset as long lpValue as long end type

you can verify the clsidIID values they are actually another struct 32 bytes consecutive of just use the hex dump of the guids the value of the actual vb.globals you want will be found at the lpValue offset.

I havent played with it as in injection yet, but its an interesting concept.

Comments: (0)

Leave Comment:
Email: (not shown)
Message: (Required)
Math Question: 87 + 32 = ? followed by the letter: T 

About Me
More Blogs
Main Site
Posts: (All)
2021 (4)
     VB6 Hijacking
     VB6 Gosub
     VB App object
2020 (8)
     AutoIT versions
     IDA JScript 2
     Using VB6 Obj files from C
     Vb6 PCode Internals
     Vb6 Runtime ForLoop Disasm
     VB6 Pcode - For Loops
     Yara Corrupt Imports
     Yara Undefined values
2019 ( 12 )
2017 ( 5 )
2016 ( 4 )
2015 ( 6 )
2014 ( 5 )
2013 ( 9 )
2012 ( 13 )
2011 ( 19 )
2010 ( 11 )
2009 ( 1 )