how to list and call a vb6 std exe class,forms and module methods
Hello Trick,
Using FireHacker's Name based object factory we can identify all (classes,forms ,modules etc).
Can you show me a vb6 working code example for the following:
how to list these (classes,forms,modules)methods and call them.
I know that we can use vbanew to create objects of forms,classes.
After creating the object using vbanew how to list and call their methods(class and form methods).
Similarly after listing Modules how to list their methods(module functionc) and call them.
For example suppose a vb6 std exe has a form1,class1 and a module1 each with one method Then how to list and call this methods thru their corresponding class object,form object and module.
Re: how to list and call a vb6 std exe class,forms and module methods
Be careful. Not all of this works the same between compiled and running in the IDE. Whenever you get something the way you like, be sure to compile it and make sure it still works.
Typically, all your "Private" and "Friend" procedures will disappear. Also, I'm not sure if anything is available for BAS modules once compiled.
Some of what you're looking for can be found here. Specifically, if you study that VtableOffsetForVb6ComMethod procedure, when supplied an object, you'll see that it's looping through all the methods of that object. You could rearrange that to get a list of those methods.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: how to list and call a vb6 std exe class,forms and module methods
Also, on another thought, if you're just wanting something for the IDE, you could just write something (maybe an Add-In) to go through the source code. Or, the extensibility model may already just have all of this.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: how to list and call a vb6 std exe class,forms and module methods
Hello Elroy,
With Trick's CreatePrivateClass code shown below from modMultiThreading2.bas we can create a private class object using vbaNew from vbheader info of std exe and call their methods using callbyname or dispcallfunc.
Similarly I was asking a way to get the address of module methods after getting
the module name thru vbheader info and call them using dispcallfunc.
A simple example with only one form, one class and one module each with one public method demo is enough for me.
Code:
' // Create private class
Private Function CreatePrivateClass( _
ByVal pClassName As Long, _
ByVal pIID As Long, _
ByRef cObj As IUnknown) As Long
Dim bIsInIDE As Boolean
Dim pProjInfo As Long
Dim pObjTable As Long
Dim pObjDesc As Long
Dim lTotalObjects As Long
Dim lIndex As Long
Dim lModuleType As Long
Dim sClassName As String
Dim pModname As Long
Dim pObjInfo As Long
Dim cTempObj As IUnknown
Dim iTypes(1) As Integer
Dim pArgs(1) As Long
Dim vArgs(1) As Variant
Dim vResult As Variant
Debug.Assert MakeTrue(bIsInIDE)
If bIsInIDE Then
sClassName = SysAllocStringByteLen(ByVal pClassName, lstrlen(pClassName))
EbExecuteLine StrPtr("modMultithreading.QueueObject new " & sClassName), 0, 0, 0
Set cTempObj = QueueObject(Nothing)
Else
' // Go thru modules
GetMem4 ByVal pVBHeader + &H30, pProjInfo
GetMem4 ByVal pProjInfo + &H4, pObjTable
GetMem2 ByVal pObjTable + &H2A, lTotalObjects
GetMem4 ByVal pObjTable + &H30, pObjDesc
For lIndex = 0 To lTotalObjects - 1
GetMem4 ByVal pObjDesc + &H28, lModuleType
GetMem4 ByVal pObjDesc + &H18, pModname
' // Only object modules
If (lModuleType And 3) = 3 Then
If lstrcmp(pClassName, pModname) = 0 Then
GetMem4 ByVal pObjDesc, pObjInfo
Set cTempObj = vbaNew(ByVal pObjInfo)
Exit For
End If
End If
pObjDesc = pObjDesc + &H30
Next
End If
If cTempObj Is Nothing Then
CreatePrivateClass = &H80040154
Exit Function
End If
' // Query interface
iTypes(0) = vbLong: iTypes(1) = vbLong
vArgs(0) = pIID: vArgs(1) = VarPtr(cObj)
pArgs(0) = VarPtr(vArgs(0)): pArgs(1) = VarPtr(vArgs(1))
CreatePrivateClass = DispCallFunc(ByVal ObjPtr(cTempObj), 0, CC_STDCALL, vbLong, 2, iTypes(0), pArgs(0), vResult)
If CreatePrivateClass >= 0 Then
CreatePrivateClass = vResult
End If
End Function
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by smkperu
With Trick's CreatePrivateClass code shown below from modMultiThreading2.bas we can create a private class object using vbaNew from vbheader info of std exe and call their methods using callbyname or dispcallfunc.
Why would you want to do this when you can always directly call MyObj.MyMethod even if MyObj is an instance of a private class.
Not to mention that you can New MyClass on private classes from within your project too, there is no need to "reflect" so much unless you are injecting a foreign process at which point I'll just shut up and advice everyone to withheld whatever advice they have here.
Re: how to list and call a vb6 std exe class,forms and module methods
I'm really hesitant to want topics censored because they can be misused, since even injecting foreign processes has legitimate uses and that knowledge should be available, but this guy has been consistently refusing to explain what he's trying to do for like a year now.
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by fafalone
I'm really hesitant to want topics censored because they can be misused, since even injecting foreign processes has legitimate uses and that knowledge should be available, but this guy has been consistently refusing to explain what he's trying to do for like a year now.
Hello Fafalone,
I am trying to understand how any vb6 std exe project executes its resources like forms, classes etc from Trick's modMultiThreading code.
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by smkperu
But how is the address of module methods found after getting
the module name thru vbheader info and call them using dispcallfunc.
Again, both finding the address to a Public method in an instantiated class (within your project) is outlined in post #3. And also how you'd call it with dispcallfunc is also outlined.
Good luck with it.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: how to list and call a vb6 std exe class,forms and module methods
Hello Trick,
I made a simple std exe application which identifies the Module1 present in
the project thru projectinfo(vbheader) when we click on the button on default form(Form1). using following code based on your modmultithreading module.
Code:
Private Sub Command1_Click()
sMethodName = UCase$("Module1")
''''''''''''''''''''''''''''''''
Dim pProjInfo As Long
Dim pObjTable As Long
Dim pObjDesc As Long
Dim lTotalObjects As Long
Dim lIndex1 As Long
Dim lModuleType As Long
Dim sClassName As String
Dim pModname As Long
Dim pObjInfo As Long
' // Go thru modules
GetMem4 ByVal pVBHeader + &H30, pProjInfo
GetMem4 ByVal pProjInfo + &H4, pObjTable
GetMem2 ByVal pObjTable + &H2A, lTotalObjects
GetMem4 ByVal pObjTable + &H30, pObjDesc
'MsgBox "for"
For lIndex1 = 0 To lTotalObjects - 1
GetMem4 ByVal pObjDesc + &H28, lModuleType
GetMem4 ByVal pObjDesc + &H18, pModname
If sMethodName = UCase$(SysAllocStringByteLen(ByVal pModname, lstrlen(ByVal pModname))) Then
MsgBox "Found " & UCase$(SysAllocStringByteLen(ByVal pModname, lstrlen(ByVal pModname))) ' success
GetMem4 ByVal pObjDesc, pObjInfo
Exit For
End If
pObjDesc = pObjDesc + &H30
Next
'How to identify Module1 method modfunc1 and run it
End Sub
Now how can I identify method modfunc1 from the Module1 module and run it.
I know that we can use addressof operator for calling standard module functions
in a std exe project.
But if we don't have any forms or classes and only standard module in the project how will sub main call any user defined module method from the module internally thru projectinfo(vbheader).
Re: how to list and call a vb6 std exe class,forms and module methods
Smkperu, I'm certainly open to being proven wrong, but I don't believe anything about a list of procedure names is saved for BAS modules once the program is compiled. And, anything that's not available once compiled, I wouldn't want to use in the IDE.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by Elroy
Smkperu, I'm certainly open to being proven wrong, but I don't believe anything about a list of procedure names is saved for BAS modules once the program is compiled. And, anything that's not available once compiled, I wouldn't want to use in the IDE.
Hello Elroy,
It is not that I want to prove anybody wrong.
Already you have shown how to call module functions thru private objects
like forms and classes and how to use DispCallFunc with standard module
functions.
When it is possible using objects thru projectinfo or vbheader even in compiled
code then why not for standard module functions directly without using them
thru instantiated objects.
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by smkperu
Hello Elroy,
It is not that I want to prove anybody wrong.
Already you have shown how to call module functions thru private objects
like forms and classes and how to use DispCallFunc with standard module
functions.
When it is possible using objects thru projectinfo or vbheader even in compiled
code then why not for standard module functions directly without using them
thru instantiated objects.
Thanks
Ahhh, ok, I think I can answer that question.
All "objects" (forms, classes, user controls, data reports) have what's called a VTable which jumps into each of the procedures it contains. Furthermore, for late-bound purposes, these objects maintain a "lookup list" of all the Public procedures within the objects. That's why this works with objects. However, BAS modules are not objects (at least not in the strictest sense), and therefore don't have VTables nor lookup lists. When compiled, any Intellisense-type lookup list that existed is thrown out because it's just not needed.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by Elroy
Ahhh, ok, I think I can answer that question.
All "objects" (forms, classes, user controls, data reports) have what's called a VTable which jumps into each of the procedures it contains. Furthermore, for late-bound purposes, these objects maintain a "lookup list" of all the Public procedures within the objects. That's why this works with objects. However, BAS modules are not objects (at least not in the strictest sense), and therefore don't have VTables nor lookup lists. When compiled, any Intellisense-type lookup list that existed is thrown out because it's just not needed.
Hello Elroy,
You are accessing thru instantiated objects using vTable.But I was asking Trick thru vbheader for accessing already existing global things like standard Modules and their method
addresses.For example you can access even existing form object(instantiated object) thru vbheader.
Re: how to list and call a vb6 std exe class,forms and module methods
Hello Trick,
We can identify instantiated form objects from vbheader thru Forms collection object.
How can we identify instantiated class objects and modules thru vbheader.
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by dz32
I will not give an example beyond this.
consider the following:
Code:
'Module 1
Dim a As Class1
Dim b As Object
Dim c As Object
Sub Main()
Set a = New Class1
Set b = New Class1
Set c = New Class1
a.name = "dog"
b.name = "cat"
c.name = "bird"
InputBox "", , Hex(ObjPtr(a)) & " " & Hex(ObjPtr(b)) & " " & Hex(ObjPtr(c))
End Sub
'Class 1 code
Public name As String
Private Sub Class_Terminate()
MsgBox "terminating " & name
End Sub
Since the vars are owned at global module level, they are only torn down at program end, so what triggers the tear down and how does the runtime find them?
Then I also have to know further from this structures how to traverse the embedded sub structures in these main structures following the correct offsets so that
I can reach and explore any existing object and then access their methods/properties.
Re: how to list and call a vb6 std exe class,forms and module methods
just added a new form to vbdec for fun Remote -> Live Class Instances
Since it already knows all of the class public variables and types, we are then able to extract the actual
values from each class instance to display them.
basically just disassemble the exe, then start up an instance of the app and we can query live data from it
should be useful for anyone looking to see how many live you classes you have at a given point, their live reference count, and what their
public variable values are. This was a bucket list feature.
Looks like all objects are tracked not just vb classes, poking at that now.
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by dz32
just added a new form to vbdec for fun Remote -> Live Class Instances
Since it already knows all of the class public variables and types, we are then able to extract the actual
values from each class instance to display them.
basically just disassemble the exe, then start up an instance of the app and we can query live data from it
should be useful for anyone looking to see how many live you classes you have at a given point, their live reference count, and what their
public variable values are. This was a bucket list feature.
Looks like all objects are tracked not just vb classes, poking at that now.
Offset Name Description
0x0 szVbMagic “VB5!” String
0x4 wRuntimeBuild Build of the VB6 Runtime
0x6 szLangDll Language Extension DLL
0x14 szSecLangDll 2nd Language Extension DLL
0x22 wRuntimeRevision Internal Runtime Revision
0x24 dwLCID LCID of Language DLL
0x28 dwSecLCID LCID of 2nd Language DLL
0x2C lpSubMain Pointer to Sub Main Code
0x30 lpProjectData Pointer to Project Data
0x34 fMdlIntCtls VB Control Flags for IDs < 32
0x38 fMdlIntCtls2 VB Control Flags for IDs > 32
0x3C dwThreadFlags Threading Mode
0x40 dwThreadCount Threads to support in pool
0x44 wFormCount Number of forms present
0x46 wExternalCount Number of external controls
0x48 dwThunkCount Number of thunks to create
0x4C lpGuiTable Pointer to GUI Table
0x50 lpExternalTable Pointer to External Table
0x54 lpComRegisterData Pointer to COM Information
0x58 bSZProjectDescription Offset to Project Description
0x5C bSZProjectExeName Offset to Project EXE Name
0x60 bSZProjectHelpFile Offset to Project Help File
0x64 bSZProjectName Offset to Project Name
ProjectInfo structure
0x0 dwVersion 5.00 in Hex (0x1F4). Version.
0x4 lpObjectTable Pointer to the Object Table
0x8 dwNull Unused value after compilation.
0xC lpCodeStart Points to start of code. Unused.
0x10 lpCodeEnd Points to end of code. Unused.
0x14 dwDataSize Size of VB Object Structures. Unused.
0x18 lpThreadSpace Pointer to Pointer to Thread Object.
0x1C lpVbaSeh Pointer to VBA Exception Handler
0x20 lpNativeCode Pointer to .DATA section.
0x24 szPathInformation Contains Path and ID string. < SP6
0x234 lpExternalTable Pointer to External Table.
0x238 dwExternalCount Objects in the External Table.
ObjectTable structure
0x0 lpHeapLink Unused after compilation, always 0.
0x4 lpExecProj Pointer to VB Project Exec COM Object.
0x8 lpProjectInfo2 Secondary Project Information.
0xC dwReserved Always set to -1 after compiling. Unused
0x10 dwNull Not used in compiled mode.
0x14 lpProjectObject Pointer to in-memory Project Data.
0x18 uuidObject GUID of the Object Table.
0x28 fCompileState Internal flag used during compilation.
0x2A dwTotalObjects Total objects present in Project.
0x2C dwCompiledObjects Equal to above after compiling.
0x2E dwObjectsInUse Usually equal to above after compile.
0x30 lpObjectArray Pointer to Object Descriptors
0x34 fIdeFlag Flag/Pointer used in IDE only.
0x38 lpIdeData Flag/Pointer used in IDE only.
0x3C lpIdeData2 Flag/Pointer used in IDE only.
0x40 lpszProjectName Pointer to Project Name.
0x44 dwLcid LCID of Project.
0x48 dwLcid2 Alternate LCID of Project.
0x4C lpIdeData3 Flag/Pointer used in IDE only.
0x50 dwIdentifier Template Version of Structure.
publicobjectdescriptor structure
0x0 lpObjectInfo Pointer to the Object Info for this Object.
0x4 dwReserved Always set to -1 after compiling.
0x8 lpPublicBytes Pointer to Public Variable Size integers.
0xC lpStaticBytes Pointer to Static Variable Size integers.
0x10 lpModulePublic Pointer to Public Variables in DATA section
0x14 lpModuleStatic Pointer to Static Variables in DATA section
0x18 lpszObjectName Name of the Object.
0x1C dwMethodCount Number of Methods in Object.
0x20 lpMethodNames If present, pointer to Method names array.
0x24 bStaticVars Offset to where to copy Static Variables.
0x28 fObjectType Flags defining the Object Type.
0x2C dwNull Not valid after compilation.
ObjectInfo structure
0x0 wRefCount Always 1 after compilation.
0x2 wObjectIndex Index of this Object.
0x4 lpObjectTable Pointer to the Object Table
0x8 lpIdeData Zero after compilation. Used in IDE only.
0xC lpPrivateObject Pointer to Private Object Descriptor.
0x10 dwReserved Always -1 after compilation.
0x14 dwNull Unused.
0x18 lpObject Back-Pointer to Public Object Descriptor.
0x1C lpProjectData Pointer to in-memory Project Object. ' what is this structure and how to get pRunInstMgr from this to get existing Form1,Class1 or Module object finally
0x20 wMethodCount Number of Methods
0x22 wMethodCount2 Zeroed out after compilation. IDE only.
0x24 lpMethods Pointer to Array of Methods.
0x28 wConstants Number of Constants in Constant Pool.
0x2A wMaxConstants Constants to allocate in Constant Pool.
0x2C lpIdeData2 Valid in IDE only.
0x30 lpIdeData3 Valid in IDE only.
0x34 lpConstants Pointer to Constants Pool.
Code:
' // Go thru modules
GetMem4 ByVal pVBHeader + &H30, pProjInfo ' Pointer to ProjectInfo structure from VBHeader
GetMem4 ByVal pProjInfo + &H4, pObjTable ' Pointer to ObjectTable structure from ProjectInfo
GetMem2 ByVal pObjTable + &H2A, lTotalObjects
GetMem4 ByVal pObjTable + &H30, pObjDesc 'Pointer to publicobjectdescriptor structure from ObjectTable
For lIndex = 0 To lTotalObjects - 1
GetMem4 ByVal pObjDesc + &H28, lModuleType
GetMem4 ByVal pObjDesc + &H18, pModname
sformName = SysAllocStringByteLen(ByVal pModname, lstrlen(pModname))
' // Only object modules
If (lModuleType And 3) = 3 Then
If (sformName = "Form1") Then 'success
MsgBox sformName 'displays Form2
'MsgBox pObjDesc & " : " & ObjPtr(Form1)
GetMem4 ByVal pObjDesc, pObjInfo ' Pointer to ObjectInfo structure from publicobjectdescriptor
GetMem4 ByVal pObjInfo + &H1C, lpProjectData' Pointer to in-memory Project Object structure from ObjectInfo
MsgBox "lpProjectData " & lpProjectData
GetMem4 ByVal lpProjectData+ ??? offset, pRunInstMgr
'how to get existing Form1 object next from here
Exit For
End If
End If
pObjDesc = pObjDesc + &H30
Next
End Sub
How to proceed from lpProjectData to existing Form1 object using pRunInstMgr with required offset in between.
I know that we can use addressof operator for calling standard module functions
in a std exe project.
But if we don't have any forms or classes and only standard module in the project how will sub main call any user defined module method from the module internally thru projectinfo(vbheader).
Thanks
Hello Elroy,
Using the following objectinfo or epiModule structure
Off Name
000 wRefCount
002 ObjectIndex
004 aObjectTable
008 lpIdeData
00C lpPrivateObject
010 dwReserved
014 Null2
018 aObject
01C lpProjectData
020 NumberOfProcs 'only one method TestSub1 in Module1
022 wMethodCount2
024 lpMethods ' used for getting TestSub1 method of Module1
028 iConstantsCount
02A iMaxConstants
02C lpIdeData2
030 lpIdeData3
034 lpConstantPool
to call TestSub1 from Module1 by obtaining its address as follows from projectinfo in a form code.
Code:
Public Function getaddr(addr As Long) As Long
getaddr = addr
End Function
Sub Command1_Click()
sMethodName = UCase$("Module1")
''''''''''''''''''''''''''''''''
Dim pProjInfo As Long
Dim pObjTable As Long
Dim pObjDesc As Long
Dim lTotalObjects As Long
Dim lIndex1 As Long
Dim lModuleType As Long
Dim sClassName As String
Dim pModname As Long
Dim pObjInfo As Long
Dim pModptr As Long
Dim lpProjectData As Long
Dim pRunInstMgr As Long
Dim pObjectInfo As Long
Dim pModInfo As Long
Dim pInstance As Long
Dim vRet As Variant
' // Go thru modules
GetMem4 ByVal pVBHeader + &H30, pProjInfo
GetMem4 ByVal pProjInfo + &H4, pObjTable
GetMem2 ByVal pObjTable + &H2A, lTotalObjects
GetMem4 ByVal pObjTable + &H30, pObjDesc
'MsgBox "for"
For lIndex1 = 0 To lTotalObjects - 1
GetMem4 ByVal pObjDesc + &H28, lModuleType
GetMem4 ByVal pObjDesc + &H18, pModname
If sMethodName = UCase$(SysAllocStringByteLen(ByVal pModname, lstrlen(ByVal pModname))) Then
MsgBox lModuleType & " type Found " & UCase$(SysAllocStringByteLen(ByVal pModname, lstrlen(ByVal pModname))) ' success
GetMem4 ByVal pObjDesc, pObjInfo
GetMem4 ByVal pObjInfo + &H24, pModptr
' CallBasProcedureByAddress getaddr(pModptr), vbEmpty, vRet, VarPtr(111), 222&, VarPtr(333!), 444# 'crashes
Exit For
End If
pObjDesc = pObjDesc + &H30
Next
End Sub
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by dz32
Give a man a fish and he is fed for a day
Teach a man to fish and he is fed for life.
you are correct about the offset 0x1c
you can get the rest of the information and offsets from the memory walking data I posted earlier. I do not have a structure definition but you can recgonize the pattern if you study the data.
here is a partial example you can translate
Code:
Private Function ScanCCO(cco As CCodeObject) As Boolean
Dim li As ListItem
Dim projData As Long, pRunMgr As Long, instances As Long, ptr As Long, i As Long, tmp As Long
Dim expectedProjData As Long, refs As Long
projData = cco.objinfo.lpProjectData
If Not cpi.ReadProcessLng(h, cco.objinfo.baseOffset + &H1C, expectedProjData) Then
List1.AddItem "could not read actual " & cco.name & " lpProjData ?"
Exit Function
End If
If expectedProjData <> projData Then
List1.AddItem cco.name & " lpProjData <> expected value?"
Exit Function
End If
If Not cpi.ReadProcessLng(h, projData, pRunMgr) Then
List1.AddItem cco.name & " failed to read lpProjData"
Exit Function
End If
If Not cpi.ReadProcessLng(h, pRunMgr + &HC, instances) Then
List1.AddItem cco.name & " failed to read instances count"
Exit Function
End If
List1.AddItem cco.name & " " & instances & " instances"
If Not cpi.ReadProcessLng(h, pRunMgr, ptr) Then
List1.AddItem cco.name & " failed to read first objPtr"
Exit Function
End If
If instances = 0 Or ptr = 0 Then Exit Function
Set li = lv.AddItem(Hex(ptr), lpad(refs, 3), cco.sType, cco.name)
Set li.Tag = cco
For i = 1 To instances - 1
... now walk the list of other objects
now you need to walk memory
hint learn to use a native debugger or memory viewer so you can see the values in memory and know what to expect the code to return.
Hello dz32,
I am able to get objptr of one object of same type and still have to work on getting other ocurrences of the same type.
to call TestSub1 from Module1 by obtaining its address as follows from projectinfo in a form code.
Code:
Public Function getaddr(addr As Long) As Long
getaddr = addr
End Function
Sub Command1_Click()
sMethodName = UCase$("Module1")
''''''''''''''''''''''''''''''''
Dim pProjInfo As Long
Dim pObjTable As Long
Dim pObjDesc As Long
Dim lTotalObjects As Long
Dim lIndex1 As Long
Dim lModuleType As Long
Dim sClassName As String
Dim pModname As Long
Dim pObjInfo As Long
Dim pModptr As Long
Dim lpProjectData As Long
Dim pRunInstMgr As Long
Dim pObjectInfo As Long
Dim pModInfo As Long
Dim pInstance As Long
Dim vRet As Variant
' // Go thru modules
GetMem4 ByVal pVBHeader + &H30, pProjInfo
GetMem4 ByVal pProjInfo + &H4, pObjTable
GetMem2 ByVal pObjTable + &H2A, lTotalObjects
GetMem4 ByVal pObjTable + &H30, pObjDesc
'MsgBox "for"
For lIndex1 = 0 To lTotalObjects - 1
GetMem4 ByVal pObjDesc + &H28, lModuleType
GetMem4 ByVal pObjDesc + &H18, pModname
If sMethodName = UCase$(SysAllocStringByteLen(ByVal pModname, lstrlen(ByVal pModname))) Then
MsgBox lModuleType & " type Found " & UCase$(SysAllocStringByteLen(ByVal pModname, lstrlen(ByVal pModname))) ' success
GetMem4 ByVal pObjDesc, pObjInfo
GetMem4 ByVal pObjInfo + &H24, pModptr
' CallBasProcedureByAddress getaddr(pModptr), vbEmpty, vRet, VarPtr(111), 222&, VarPtr(333!), 444# 'crashes
Exit For
End If
pObjDesc = pObjDesc + &H30
Next
End Sub
I was asking for getting a address of standard module public method (pName) from pPubDesc structure pNames array using only publicdescriptor (pPubDesc ) structure (in which there is no privatedescriptor(pPrivDesc ) involved) for the objectinfo or epimodule structure in https://www.vbforums.com/attachment....6&d=1674314835
Re: how to list and call a vb6 std exe class,forms and module methods
I feel like I've said this several times before...
Yes, there are structures that track the procedure names of a standard (BAS) module. But the procedure names in those structures are only used by Intellisense (and the IDE's extensibility model). All those procedure names (of BAS modules) are zeroed out when your program is compiled to an EXE (or DLL, or OCX).
And, for me, something that doesn't survive compilation is useless to me. If you want it just in the IDE, then write an Add-In and use the extensibility model.
The above is also true for Private and Friend procedures in classes. The only procedure names you can get once compiled, are Public procedure names in an actual class (CLS, FRM, CTL, PAG, DSR) ... and not in a BAS module. During compilation, everything else is resolved to a linkable/relocatable memory address (with the procedure's name gone).
I'm not sure how else to be more clear.
----------------
ADDED: Just as more "proof" of this, this is why CallByName only works with a Public procedure of an object instantiated from a class, and not any BAS procedure.
Last edited by Elroy; Jan 23rd, 2023 at 12:30 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by Elroy
I feel like I've said this several times before...
Yes, there are structures that track the procedure names of a standard (BAS) module. But the procedure names in those structures are only used by Intellisense (and the IDE's extensibility model). All those procedure names (of BAS modules) are zeroed out when your program is compiled to an EXE (or DLL, or OCX).
And, for me, something that doesn't survive compilation is useless to me. If you want it just in the IDE, then write an Add-In and use the extensibility model.
The above is also true for Private and Friend procedures in classes. The only procedure names you can get once compiled, are Public procedure names in an actual class (CLS, FRM, CTL, PAG, DSR) ... and not in a BAS module. During compilation, everything else is resolved to a linkable/relocatable memory address (with the procedure's name gone).
I'm not sure how else to be more clear.
----------------
ADDED: Just as more "proof" of this, this is why CallByName only works with a Public procedure of an object instantiated from a class, and not any BAS procedure.
Honestly, you're just wasting your time trying to "help" this poster.
Re: how to list and call a vb6 std exe class,forms and module methods
smkperu, just as a final thought on this ... one thing you could do is to create a bunch of global Long variables (Public in a BAS module), and then use AddressOf to save the address of whatever BAS procedures you wanted, possibly doing that when your project starts. Then, you can use those global Long variables as memory pointers to whatever BAS procedures you wanted (even Friend and Private procedures). But that's quite different from what you're asking, but it would work, as once your program is loaded, those addresses won't change. But you can't save them in a file or anything, as they may change on each loading of your program (but I'm not entirely sure on that point). They definitely won't change once your program is up and running.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by Shaggy Hiker
This is just a common misconception. The actual quote was:
Give a man a fish and he is fed for a day.
Teach a man to fish and he will buy a boat.
That's not so relevant, here.
*shakes head at Shaggy*
Out the back of my boat. Truth be told, I love to go boating, but I'm not much of a fisherman.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Can you explain how to get Main and abc addresses as 4010D4 and 4010E0 from lpMethods and NumberOfProcs in the structure above.
Further both Main and abc are shown as Proc_401500 and Proc_401498.How are this Proc_?????? related to Main and abc.
Re: how to list and call a vb6 std exe class,forms and module methods
Your example addresses were for pcode exe. To understand why the addresses are different you also need to understand what the data is at those addresses. In pcode AddressOf returns a native stub to transition to actual pcode body.
You should use free version of IDA disassembler to look at addresses. To work with these things you must remove the mystery and learn how to explore the file format for answers.
If you are trying to call the pcode module function, then you will need address returned by addressof, not the actual pcode body address which I list in vbdec. The native stubs are also listed in their own node on the main treeview for exploring.
pcode:
msgbox 4010e0
msgbox 4010ec
004010ec BA54154000 mov edx,0x401554 ;structure defining pcode method
004010f1 B932104000 mov ecx,0x401032 ; jmp ProcCallEngine
004010f6 FFE1 jmp ecx
004010E0 mov edx, 4014D8h ;structure defining pcode method
004010E5 mov ecx, 0x401032 ; jmp ProcCallEngine
004010EA jmp ecx
Methods:
Proc_4014A4 sz: 52 va: 4014A4 last: 4014D8 Module1.Proc_4014A4
Proc_40151C sz: 56 va: 40151C last: 401554 Module1.Sub Main
Dim procAddr() As Long
If NumberOfProcs > 0 Then 'pcode only
ReDim procAddr(NumberOfProcs - 1)
Seek #f, VaToFileOffset(lpMethods) + 1 'looks never valid for vb5? diff struct?
Get #f, , procAddr()
For i = 0 To UBound(procAddr)
If procAddr(i) <> 0 Then
If Not isInTextSect(procAddr(i)) Then
addLog "************* Error ObjInfo(" & Hex(baseOffset) & ").loadSelf: " & owner.name & " Proc(" & i & ")"
addLog " *** Garbage procAddr " & Hex(procAddr(i)) & " foff: " & (VaToFileOffset(lpMethods) + (i * 4))
Else
lpMethods points to an array of addresses for the pcode structures, this is not usable unless you want to use the"Binary reuse of pcode functions" technique.
The addressof stubs to allow for native code execution are only included if an actual addressof call was used. however you can create your own this is what this does
For native code, addressof is the actual address of the real code, but there is no table that I have found that keeps all of the addresses like for pcode.
for native, I have to scan the code looking for function signatures or analyze the disassembly for functions I do know about. I think trick has a command line option for linker that will generate MAP file if you are working on code you control.
You would have to work out your own ScanNativeModuleFunctions mine is big and intertwined with other parts of program. basic signature is below, but does not catch everything
Code:
'Signature 55 8B EC 83 EC ?? 68 ?? ?? ?? ?? 64 A1 00 00 00 00 50 64 89 25 00 00 00 00
' _generally_ native module functions start with the following:
' .text:00401EA0 55 push ebp
' .text:00401EA1 8B EC mov ebp, esp
' .text:00401EA3 83 EC 08 sub esp, 8
' .text:00401EA6 68 56 11 40 00 push offset __vbaExceptHandler
' .text:00401EAB 64 A1 00 00 00 00 mov eax, large fs:0
' .text:00401EB1 50 push eax
' .text:00401EB2 64 89 25 00 00 00 00 mov large fs:0, esp
'.text:00472FA0 55 push ebp
'.text:00472FA1 8B EC mov ebp, esp
'.text:00472FA3 83 EC 14 sub esp, 14h
'.text:00472FA6 68 D6 8D 40 00 push offset ___vbaExceptHandler
'.text:00472FAB 64 A1 00 00 00 00 mov eax, large fs:0
'.text:00472FB1 50 push eax
'some procs end up almost nothing?
'Public Sub mod1_1(ByVal x As Long, ByRef f As Form, ParamArray z())
' x = "mod1_1"
'End Sub
'
'.text:00401DA0 sub_401DA0 proc near
'.text:00401DA0 push offset aMod11 ; "mod1_1"
'.text:00401DA5 call ds:__vbaI4Str
'.text:00401DAB retn 0Ch
'.text:00401DAB sub_401DA0 endp
Re: how to list and call a vb6 std exe class,forms and module methods
Originally Posted by dz32
Your example addresses were for pcode exe. To understand why the addresses are different you also need to understand what the data is at those addresses. In pcode AddressOf returns a native stub to transition to actual pcode body.
You should use free version of IDA disassembler to look at addresses. To work with these things you must remove the mystery and learn how to explore the file format for answers.
If you are trying to call the pcode module function, then you will need address returned by addressof, not the actual pcode body address which I list in vbdec. The native stubs are also listed in their own node on the main treeview for exploring.
pcode:
msgbox 4010e0
msgbox 4010ec
004010ec BA54154000 mov edx,0x401554 ;structure defining pcode method
004010f1 B932104000 mov ecx,0x401032 ; jmp ProcCallEngine
004010f6 FFE1 jmp ecx
004010E0 mov edx, 4014D8h ;structure defining pcode method
004010E5 mov ecx, 0x401032 ; jmp ProcCallEngine
004010EA jmp ecx
Methods:
Proc_4014A4 sz: 52 va: 4014A4 last: 4014D8 Module1.Proc_4014A4
Proc_40151C sz: 56 va: 40151C last: 401554 Module1.Sub Main
Dim procAddr() As Long
If NumberOfProcs > 0 Then 'pcode only
ReDim procAddr(NumberOfProcs - 1)
Seek #f, VaToFileOffset(lpMethods) + 1 'looks never valid for vb5? diff struct?
Get #f, , procAddr()
For i = 0 To UBound(procAddr)
If procAddr(i) <> 0 Then
If Not isInTextSect(procAddr(i)) Then
addLog "************* Error ObjInfo(" & Hex(baseOffset) & ").loadSelf: " & owner.name & " Proc(" & i & ")"
addLog " *** Garbage procAddr " & Hex(procAddr(i)) & " foff: " & (VaToFileOffset(lpMethods) + (i * 4))
Else
lpMethods points to an array of addresses for the pcode structures, this is not usable unless you want to use the"Binary reuse of pcode functions" technique.
The addressof stubs to allow for native code execution are only included if an actual addressof call was used. however you can create your own this is what this does
For native code, addressof is the actual address of the real code, but there is no table that I have found that keeps all of the addresses like for pcode.
for native, I have to scan the code looking for function signatures or analyze the disassembly for functions I do know about. I think trick has a command line option for linker that will generate MAP file if you are working on code you control.
You would have to work out your own ScanNativeModuleFunctions mine is big and intertwined with other parts of program. basic signature is below, but does not catch everything
Code:
'Signature 55 8B EC 83 EC ?? 68 ?? ?? ?? ?? 64 A1 00 00 00 00 50 64 89 25 00 00 00 00
' _generally_ native module functions start with the following:
' .text:00401EA0 55 push ebp
' .text:00401EA1 8B EC mov ebp, esp
' .text:00401EA3 83 EC 08 sub esp, 8
' .text:00401EA6 68 56 11 40 00 push offset __vbaExceptHandler
' .text:00401EAB 64 A1 00 00 00 00 mov eax, large fs:0
' .text:00401EB1 50 push eax
' .text:00401EB2 64 89 25 00 00 00 00 mov large fs:0, esp
'.text:00472FA0 55 push ebp
'.text:00472FA1 8B EC mov ebp, esp
'.text:00472FA3 83 EC 14 sub esp, 14h
'.text:00472FA6 68 D6 8D 40 00 push offset ___vbaExceptHandler
'.text:00472FAB 64 A1 00 00 00 00 mov eax, large fs:0
'.text:00472FB1 50 push eax
'some procs end up almost nothing?
'Public Sub mod1_1(ByVal x As Long, ByRef f As Form, ParamArray z())
' x = "mod1_1"
'End Sub
'
'.text:00401DA0 sub_401DA0 proc near
'.text:00401DA0 push offset aMod11 ; "mod1_1"
'.text:00401DA5 call ds:__vbaI4Str
'.text:00401DAB retn 0Ch
'.text:00401DAB sub_401DA0 endp
Hello dz32,
Based on your explanation I checked in IDA disassembler and understood that
Signature 55 8B EC 83 EC ?? 68 ?? ?? ?? ?? 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 in Hexview is working only for some native functions in general.
So if not possible using signature just as you specified for the following code
Code:
Public Sub mod1_1(ByVal x As Long, ByRef f As Form, ParamArray z())
x = "mod1_1"
End Sub
what is the other way to follow like as you specified how to detect a function has no signature in Hexview and then analyze the disassembly for this native functions in vb6.
Re: how to list and call a vb6 std exe class,forms and module methods
I do not currently detect native functions without that signature I was mostly focused on pcode executables.
When I get around to building better detections my next step will be to analyze the disassembly of all of the functions I do know about looking for call instructions to unknown functions. Even ida can not find all functions in vb.
Reversing is not perfect it still takes manual analysis in many places.