rtcTypeName


Author: David Zimmer
Date: 05.26.21 - 7:14am



 
Dim i As Long, c As New Class1, s As String

s = TypeName(i)
s = TypeName(c)
    
Lets consider the following pcode:
	
401C08    04 78FF               FLdRfVar var_88
401C0B    4D 5CFF0340           CVarRef var_A4  0x4003 (I4 | ByRef)
401C10    0B 00000400           ImpAdCallI2 rtcTypeName 0x4
401C15    31 70FF               FStStr var_90
401C18    04 74FF               FLdRfVar var_8C
401C1B    56 0100               NewIfNullAd Class1
401C1E    FCF8 58FF             FStAd var_A8
401C22    04 58FF               FLdRfVar var_A8
401C25    4D 5CFF0940           CVarRef var_A4  0x4009 (IDisp | ByRef)
401C2A    0B 00000400           ImpAdCallI2 rtcTypeName 0x4
	
So rtcTypeName takes a variant as the argument. In both examples our hard type
is first converted to a variant with CVarRef.

Inside the msvbvm60.dll rtcTypeName export, there are several code paths.

If the variant.vt field is one of the COM (and VB) intrinsic types, then 
the value is used as a direct lookup into a hardcoded string array.

6608D8F9   MOV EDI,DWORD PTR DS:[EDI*4+66116070]

Thats where it looks up the string name from the numeric type as an offset into the array at
66116070, looking at that address in olly dump window view as long address shows:

$ ==> >6609B724 UNICODE "Empty" ; element 0 Const vbEmpty = 0
$+4 >6609B718 UNICODE "Null" ; element 1 Const vbNull = 1
$+8 >6609B708 UNICODE "Integer"
$+C >6609B6FC UNICODE "Long"
$+10 >6609B6EC UNICODE "Single"
$+14 >6609B6DC UNICODE "Double"
$+18 >6609B6C8 UNICODE "Currency"
$+1C >6609B6BC UNICODE "Date"
$+20 >6609B6AC UNICODE "String"
$+24 >6609B69C UNICODE "Object" ; element 9 Const vbObject = 9
$+28 >6609B690 UNICODE "Error"
$+2C >6609B680 UNICODE "Boolean"
$+30 >6609B670 UNICODE "Variant"
$+34 >6609B660 UNICODE "Unknown"
$+38 >6609B650 UNICODE "Decimal"
$+3C >66001E62 MSVBVM60.66001E62 -> 00000000 element 15
$+40 >66001E62 MSVBVM60.66001E62
$+44 >6609B644 UNICODE "Byte" Const vbByte = 17
$+48 >6609B634 UNICODE "Record"

If its a class object (even a vb user class) then it takes the following path

if ( (**v6)(v6, &IID_IProvideClassInfo, &v23) < 0 )// QueryInterface
{
	if ( (**v6)(v6, &IID_IDispatch, &v22) < 0 )
	  goto LABEL_60;
	v7 = (*(*v22 + 16))(v22, 0, 1033, &v24);    // MSVBVM60.BASIC_DISPINTERFACE_GetTypeInfo
	v8 = v22;
}
...
v9 = (*(*v24 + 48))(v24, -1, &Dest, 0, 0, 0); // MSVBVM60.CEcTypeInfo::GetDocumentation

Finally it returns the string name retrieved with an alloc and copy

v13 = wcslen(v12);
Dest = SysAllocStringLen(0, v13 + 2);
wcscpy(Dest, v12); 

If its an array the () are manually added later.

rtcVarType, also receives the converted type as a variant, and then just
extracts the variant.vt field numeric value. It does a little error 
checking, but no need for a string lookup, class query, and string alloc.
So it will be much faster. 





Comments: (0)

 
Leave Comment:
Name:
Email: (not shown)
Message: (Required)
Math Question: 11 + 72 = ? followed by the letter: Y 



Twitter
RSS
About Me
More Blogs
Main Site
Posts: (All)
2021 (4)
     VB6 Hijacking
     rtcTypeName
     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 )