VB6反编译详解 by Kenmark-Fenix
**************************************************
最新于2006-7-13更新!
**************************************************
写本文已经惦记了好几年了,由于一直没有完整的资料和充裕的时间,所以一直没有动手。
在这里一方面是写给大家看看,另一方面是招募更多有志于反编译VB6的同志们一起来研究学习!
我的E-MAIL:ken.mingyuan@hotmail.com ken.mingyuan@gmail.com
我的BLOG: blog.csdn.net/kenmark
我的QQ:188916915
十分期待着与大家一起学习!
――Kenmark
VB6是一个半编译半解释的语言,编译后程序主要在运行库MSVBVM60.DLL下转悠,通过与MSVBVM60的互动来完成程序运行的过程。
1.引入(参考:《VB程序大揭密》我的博客上有转载http://blog.csdn.net/Kenmark/archive/2005/08/11/450985.aspx)
我们用W32DASM打开一个中型的VB程序来反汇编,我们发现程序中用到的MSGBOX÷FileCopy等理应对应API函数居然一个都没有出现在编译后程序的IMPORT TABLE里,一般VC和DEPHI都是直接出现在编译后程序的IMPORT TABLE里的,而我们的VB程序用到了如此之多的API函数居然只使用了一个DLL――MSVBVM60.DLL。
然后用工具打开MSVBVM60.DLL,一看,输出的函数还真不少,其中有用__vba和rtc开头的也有直接就是函数名的,仔细一看,哇赛,可以说完全是一个windows API的代理,应有尽有:
rtcRandomize :Randomize 函数的对应API;
rtcMidCharVar :Mid 函数的对应API;
rtcLeftCharVar、rtcRightCharVar :看出来了吧,这些是Left、Right函数的对应API;
rtcUpperCaseVar :UCase 函数的对应API;
rtcKillFiles :Kill 语句的对应API;
rtcFileCopy :FileCopy 语句的对应API;
rtcFileLength :EOF、FileLen函数的对应API;
rtcGetTimer :Randomize Timer中获取Timer的对应API;
rtcShell :Shell函数的的对应API;
rtcMakeDir :MkDir 语句的对应API;
rtcRemoveDir :RmDir 语句的对应API;
rtcDir :Dir 函数的对应API;
rtcSpaceVar :Space 函数的对应API;
原来,所有VB的操作函数都是在调用MSVBVM60.DLL里面实现
前缀是rtc的是一般的语句和函数
涉及字符串处理的都叫var,例如:
__vbaUbound : UBound 的对应API;
__vbaFileOpen :Open 语句的对应API;
__vbaStrCmp :比较两个字符串:If String1 = String2 Then ......
__vbaVarOr :Or 运算符的对应API;
__vbaRedim :Redim 语句的对应API;
__vbaRedimPreserve :Redim 语句加上 Preserve 参数的对应API;
__vbaGet、vbaPut :Get、Put语句的对应API……
我们还看到一个DLL:DllFunctionCall,这个就是我们调用其他DLL时需要向MSVBVM60申请的,…………。
可以说VB的程序是一个包裹在MSVBVM60阴影控制下的孩子,所有的操作都要直接向它请求,而MSVBVM60完全可以称得上是一个代理的机器。从程序开始,到运行中的所有操作,函数调用,错误报告等等,都是由它一手包办的。
来吧,我们这里不是来介绍它是怎么构成的我们要搞掉它虚伪的外表,把我们的代码从MSVBVM60的封建保护下救出来。
我的资料大量是参考一个开源的VB程序解析程序(居然也是用VB编写的),这个程序可以完全分析出VB程序(没有加壳)的PROJECT信息以及完全将FORM变回来,对于代码呢,可以获得SUB MAIN的汇编代码地址,但是不能返回到VB代码,里面还内置了一个假的反汇编器,以后我会说的!
我提供了它的下载,大家去看看,不知道它的资料是哪里来的十分全面,就是用VB写的比较繁!还有由于界面控制太多,代码有点乱!
2.程序初始化
我们用W32DASM打开任何VB程序,跳到ENTRY POINT之后看到的总是一个PUSH *****一个地址,然构调用MSVBVM60.DLL的ThunRTMain
而在VC程序里,我们至少要看到进程的创建什么的,其实这个VB函数是一切的开端,由它开始来解析整个编译后的程序,完成系统环境的初始化,然后找到真正的程序入口,跳转到程序的领空。
所以这个PUSH指令压入栈的是VBEXE(姑且这么称呼)初始化结构的开始。我们存下这个地址(这个是一个VA要正确地转换成文件地OFFSET先要-ImageBase然后要对照块表,可以用工具完成,熟悉了一下就能看出来),然后我们跳到那里。
看看是什么,哇赛,是VB程序的招牌也!“VB5!”是所有VB程序初始化结构入口地址指向的MAGIC字符,找到这里,开始能够读取VB初始化结构了(我们现在做的就是ThunRTMain要完成的)
我们开始了!
部分名词解读:
RVA 相对虚拟地址,一般需要使用RVA2Offset来将其转换成绝对的文件偏移 变量前缀为pr或是a
VA 虚拟地址,减去IMAGEBASE就是RVA 变量前缀为p或是a
offset 相对结构的偏移 变量前缀为o
1)VBHEADER
从PE文件的ENTRY POINT进入后第一个指令是压入一个指针来表示VBHEADER的位置,这个指令为
push xxxxxxxx地址是经过基址IMAGE_BASE偏移后的地址,所以减去IMAGE_BASE后获得的就是VBHEADER开始的VA然后用PEFile类中的函数加以分析可以得到的是文件中VBHEADER的偏移量。
这个指令在机器码中是这样表示的:68 C0 11 40 00
68是PUSH的机器码,而后是内存存储方式的地址化成汇编语言就是:
push 004011c0 所以减去基址后就是11C0然后进行VA2OFFSET得到的是11c0的偏移,转向那段数据就能得到VBHEADER。
这是VBHEADER结构的C语言描述:
typedef struct
{
char Signature[4]; // 四个字节的签名符号,和PEHEADER里的那个signature是类似性质的东西,VB文件都是"VB5!"
WORD RtBuild; // 运行时创立的变量(类似编译的时间)
BYTE LangDLL[14]; // 语言DLL文件的名字(如果是0x2A的话就代表是空或者是默认的)
BYTE BakLangDLL[14]; // 备份DLL语言文件的名字(如果是0x7F的话就代表是空或者是默认的,改变这个值堆EXE文件的运行没有作用)
WORD RtDLLVer; // 运行是DLL文件的版本
DWORD LangID; // 语言的ID
DWORD BakLangID; // 备份语言的ID(只有当语言ID存在时它才存在)
DWORD pSubMain; // RVA(实际研究下来是VA) sub main过程的地址指针(3.)(如果时00000000则代表这个EXE时从FORM窗体文件开始运行的)
DWORD pProjInfo; // VA 工程信息的地址指针,指向一个ProjectInfo_t结构(2.)
DWORD fMDLIntObjs; // ?详细见"MDL 内部组建的标志表"
DWORD fMDLIntObjs2; // ?详细见"MDL 内部组建的标志表"
DWORD ThreadFlags; // 线程的标志
//* 标记的定义(ThreadFlags数值的含义)
//+-------+----------------+--------------------------------------------------------+
//| 值 | 名字 | 描述 |
//+-------+----------------+--------------------------------------------------------+
//| 0x01 | ApartmentModel | 特别化的多线程使用一个分开的模型 |
//| 0x02 | RequireLicense | 特别化需要进行认证(只对OCX) |
//| 0x04 | Unattended | 特别化的没有GUI图形界面的元素需要初始化 |
//| 0x08 | SingleThreaded | 特别化的静态区时单线程的 |
//| 0x10 | Retained | 特别化的将文件保存在内存中(只对Unattended) |
//+-------+----------------+--------------------------------------------------------+
//ex: 如果是0x15就表示是一个既有多线程,内存常驻,并且没有GUI元素要初始化
DWORD ThreadCount; // 线程个数
WORD FrmCount; // 窗体个数
WORD pExternalComponentCount; // VA 外部引用个数例如WINSOCK组件的引用
DWORD ThunkCount; // ?大概是内存对齐相关的东西
DWORD pGUITable; // VA GUI元素表的地址指针(指向一个GUITable_t结构(4.四))
DWORD pExternalComponentTable; // VA 外部引用表的地址指针
// DWORD pProjDep; // VA 工程的描述的地址指针(这个其实没有)
DWORD pComRegData; // VA COM注册数据的地址指针
DWORD oProjExename; // Offset 指向工程EXE名字的字符串
DWORD oProjTitle; // Offset 指向工程标题的字符串
DWORD oHelpFile; // Offset 指向帮助文件的字符串
DWORD oProjName; // Offset 指向工程名的字符串
}VBHeader_t;
//* MDL 内部组建的标志表
//+---------+------------+---------------+
//| ID | 值 | 组建名称 |
//+---------+------------+---------------+
//| 第一个标志 |
//+---------+------------+---------------+
//| 0x00 | 0x00000001 | PictureBox |
//| 0x01 | 0x00000002 | Label |
//| 0x02 | 0x00000004 | TextBox |
//| 0x03 | 0x00000008 | Frame |
//| 0x04 | 0x00000010 | CommandButton |
//| 0x05 | 0x00000020 | CheckBox |
//| 0x06 | 0x00000040 | OptionButton |
//| 0x07 | 0x00000080 | ComboBox |
//| 0x08 | 0x00000100 | ListBox |
//| 0x09 | 0x00000200 | HScrollBar |
//| 0x0A | 0x00000400 | VScrollBar |
//| 0x0B | 0x00000800 | Timer |
//| 0x0C | 0x00001000 | Print |
//| 0x0D | 0x00002000 | Form |
//| 0x0E | 0x00004000 | Screen |
//| 0x0F | 0x00008000 | Clipboard |
//| 0x10 | 0x00010000 | Drive |
//| 0x11 | 0x00020000 | Dir |
//| 0x12 | 0x00040000 | FileListBox |
//| 0x13 | 0x00080000 | Menu |
//| 0x14 | 0x00100000 | MDIForm |
//| 0x15 | 0x00200000 | App |
//| 0x16 | 0x00400000 | Shape |
//| 0x17 | 0x00800000 | Line |
//| 0x18 | 0x01000000 | Image |
//| 0x19 | 0x02000000 | Unsupported |
//| 0x1A | 0x04000000 | Unsupported |
//| 0x1B | 0x08000000 | Unsupported |
//| 0x1C | 0x10000000 | Unsupported |
//| 0x1D | 0x20000000 | Unsupported |
//| 0x1E | 0x40000000 | Unsupported |
//| 0x1F | 0x80000000 | Unsupported |
//+---------+------------+---------------+
//| 第二个标志 |
//+---------+------------+---------------+
//| 0x20 | 0x00000001 | Unsupported |
//| 0x21 | 0x00000002 | Unsupported |
//| 0x22 | 0x00000004 | Unsupported |
//| 0x23 | 0x00000008 | Unsupported |
//| 0x24 | 0x00000010 | Unsupported |
//| 0x25 | 0x00000020 | DataQuery |
//| 0x26 | 0x00000040 | OLE |
//| 0x27 | 0x00000080 | Unsupported |
//| 0x28 | 0x00000100 | UserControl |
//| 0x29 | 0x00000200 | PropertyPage |
//| 0x2A | 0x00000400 | Document |
//| 0x2B | 0x00000800 | Unsupported |
//+---------+------------+---------------+
//ex: 如果值是0x30F000 (那个被叫做 "静态二进制常量定义在大多数的地方")就是意味着来初始化打印机,窗体,屏幕,剪贴板,组建(0xF000)也有Drive/Dir 组建(0x30000).
//这是VB工程的一个默认的设置因为这些组建都能从一个模块中获得module (例如,他们是没有图像的除了经常被创造窗体)
2)工程信息
从VBHEADER->ProjectInfo(是一个VA)-IMAGEBASE后在通过RAV2OFFSET得到的是 工程信息 的偏移地址.
这是PROJECT_INFO结构的C语言描述:
const long MAX_PATH = 260; //最长的PATH长度
typedef struct
{
DWORD Signature; // 结构的签名特性,和魔术字符类似
DWORD pObjectTable; // VA 结构指向的组件列表的地址指针(很重要的!(7.))
DWORD Null1; // ?没有用的东西
WORD pStartOfCode; // VA 代码开始点,类似PEHEAD->EntryPoint这里告诉了VB代码实际的开始点
DWORD Flag1; // 标志1
DWORD ThreadSpace; // 多线程的空间?????????????????
DWORD pVBAExcrptionhandler; // VA VBA意外处理机器地址指针
DWORD pNativeCode; // VA 本地机器码开始位置的地址指针
WORD oProjectLocation; // Offset 工程位置?????????????????
WORD Flag2; // 标志2
WORD Flag3; // 标志3
BYTE OriginalPathName[MAX_PATH*2]; // 原文件地址,一个字符串,长度最长为MAX_PATH
BYTE NullSpacer; // 无用的东西,用来占位置????????????????????
DWORD pExternalTable; // VA 引用表的指针地址
DWORD ExternalCount; // 引用表大小(个数)
// sizeof() = 0x23c
}ProjectInfo_t;
这个东西基本包含了这个PROJECT的信息,但是主要的意义还是提供了之后的结构的索引,最重要的是它提供了传说中的OBJECT TABLE的入口地址,对于EXE里面有多少FORM,MODULE十分重要。
3)SubMain
从VBHEADER->SubMain可以获得SubMain代码的入口处,但是有些VB程序是从FORM开始运行的所以当这个值为0时就代表此程序不是从SubMain开始运行的而是从FORM开始运行的.
4)GUITable
从VBHEADER->GUITable可以获得GUI元素表的地址指针,也就是指向WINDOWS图形元素的表.
这是GUITable结构的C语言描述:
typedef struct
{
DWORD lStructSize; // 这个结构的总大小
BYTE uuidObjectGUI[15]; // Object GUI的UUID
DWORD Unknown1; // ???????????????????????????????????
DWORD Unknown2; // ???????????????????????????????????
DWORD Unknown3; // ???????????????????????????????????
DWORD Unknown4; // ???????????????????????????????????
DWORD lObjectID; // 当前工程的组件ID
DWORD Unknown5; // ???????????????????????????????????
DWORD fOLEMisc; // OLEMisc标志
BYTE uuidObject[15]; // 组件的UUID
DWORD Unknown6; // ???????????????????????????????????
DWORD Unknown7; // ???????????????????????????????????
DWORD pFormPointer; // VA 指向GUI Object Info结构的地址指针
DWORD Unknown8; // ???????????????????????????????????
// sizeof() = 0x50
}GUITable_t;
这个表没有什么重要,主要就是那个pFormPointer比较有用。
5)ExternalComponentTable
从VBHEADER->ExternalComponentTable可以获得外部引用表的地址指针.
这是ExternalTable以及ExternalLibrary的VB结构以及C语言描述:
typedef struct
{
DWORD Flag; // 标志
DWORD pExternalLibrary; // VA 指向ExternalLibrary结构的地址指针
}ExternalTable_t;
typedef struct
{
DWORD pLibraryName; // VA 指向 NTS
DWORD pLibraryFunction; // VA 指向 NTS
}ExternalLibrary_t;
6)ComRegData and COMRegInfo
从VBHEADER->ComRegData可以获得COM注册数据的地址指针.
这是COMRegData以及COMRegInfo结构的C语言描述:
typedef struct
{
DWORD oRegInfo; //Offset 指向COM Interfaces Info结构(COM接口信息)
DWORD oNTSProjectName; //Offset 指向Project/Typelib Name(工程名)
DWORD oNTSHelpDirectory; //Offset 指向Help Directory(帮助文件目录)
DWORD oNTSProjectDescription; //Offset 指向Project Description(工程描述)
BYTE uuidProjectClsId(15); //Project/Typelib的CLSID
DWORD lTlbLcid; //Type Library的LCID
WORD iPadding1; //没有用的内存对齐空间1
WORD iTlbVerMajor; //Typelib 主版本
WORD iTlbVerMinor; //Typelib 次版本
WORD iPadding2; //没有用的内存对齐空间2
DWORD lPadding3; //没有用的内存对齐空间3
// sizeof() = 0x30
}COMRegData_t;
typedef struct
{
DWORD oNextObject; //Offset to COM Interfaces Info
DWORD oObjectName; //Offset to Object Name
DWORD oObjectDescription; //Offset to Object Description
DWORD lInstancing; //Instancing Mode
DWORD lObjectID; //Current Object ID in the Project
BYTE uuidObjectClsID[15]; //CLSID of Object
DWORD fIsInterface; // Specifies if the next CLSID is valid
DWORD oObjectClsID; // Offset to CLSID of Object Interface
DWORD oControlClsID; // Offset to CLSID of Control Interface
DWORD fIsControl; // Specifies if the CLSID above is valid
DWORD lMiscStatus; // OLEMISC Flags (see MSDN docs)
BYTE fClassType; // Class Type
BYTE fObjectType; // Flag identifying the Object Type
WORD iToolboxBitmap32; // Control Bitmap ID in Toolbox
WORD iDefaultIcon; // Minimized Icon of Control Window
WORD fIsDesigner; // Specifies whether this is a Designer
DWORD oDesignerData; // Offset to Designer Data
// sizeof() = 0x44
}COMRegInfo_t;
'Object Type part of tCOMRegInfo//没有翻译的意义,就没有翻译,只是看看而已
'+-------+---------------+-------------------------------------------+
'| Value | Name | Description |
'+-------+---------------+-------------------------------------------+
'| 0x02 | Designer | A Visual Basic Designer for an Add.in |
'| 0x10 | Class Module | A Visual Basic Class |
'| 0x20 | User Control | A Visual Basic ActiveX User Control (OCX) |
'| 0x80 | User Document | A Visual Basic User Document |
'+-------+---------------+-------------------------------------------+
*7)ObjectInfo
这些东西十分重要,是提取VB工程元素的重要标志,从这里我们可以得到这个工程里有多少FORM,多少MODULE,以及他们的重要索引数据,可以说重要性和SECTION HEAD在EXE程序中重要性相同。
入口的地址是由ProjectInfo_t结构提供的(semi提供关于这里提供的资料少之又少,所以需要自己摸索)
从ProjectInfo_t开始指向的是一个ObjectTable_t,由ObjectTable_t提供第一个OBJECT_t结构的地址
typedef struct //这个是OBJECT 的总表,可以索引以后的每个OBJECT
{
DWORD lNull1 As Long; //没有用的填充东西
DWORD aExecProj; //VA指向一块内存结构(研究下来既不没见着这个东西由什么用处
DWORD aProjectInfo2; //VA指向Project Info 2
DWORD Const1; //没有用的填充东西
DWORD Null2; //没有用的填充东西
DWORD lpProjectObject As Long ' 0x14
DWORD Flag1; //标志1
DWORD Flag2; //标志2
DWORD Flag3; //标志3
DWORD Flag4; //标志4
WORD fCompileType; //Internal flag used during compilation
WORD ObjectCount1; //OBEJCT数量1????
WORD iCompiledObjects; //编译后OBJECT数量
WORD iObjectsInUse As Integer; //Updated in the IDE to correspond the total number ' but will go up or down when initializing/unloading modules.
DWORD aObject; //VA指向第一个OBJECT_t结构,很重要
DWORD Null3; //没有用的填充东西
DWORD Null4; //没有用的填充东西
DWORD Null5; //没有用的填充东西
DWORD aProjectName; //执行工程名字的字符串
DWORD LangID1; //language ID1
DWORD LangID2; //language ID2
DWORD Null6; //没有用的填充东西
DWORD Const3; //没有用的填充东西
' 0x54
}ObjectTable_t;
type struct//这个就是每个OBJECT的结构,
{
DWORD aObjectInfo; //VA 指向一个ObjectInfo_t类型,来显示这个OBJECT的数据
DWORD Const1; //没有用的填充东西
DWORD aPublicBytes; //VA 指向公用变量表大小
DWORD aStaticBytes; //VA 指向静态变量表地址
DWORD aModulePublic; //VA 指向公用变量表
DWORD aModuleStatic; //VA 指向静态变量表
DWORD aObjectName; //VA 字符串,这个OBJECT的名字
DWORD ProcCount; // events, funcs, subs(时间\函数\过程)数目
DWORD aProcNamesArray; //VA 一般都是0
DWORD oStaticVar; //OFFSET 从aModuleStatic指向的静态变量表偏移
DWORD ObjectType; //比较重要显示了这个OBJECT的实行,具体见下表
DWORD Null3; //没有用的填充东西
//sizeof() = 0x30
}Object_t;
'Object_t.ObjectTyper 属性...//重要的属性表部分
'#########################################################
'form: 0000 0001 1000 0000 1000 0011 --> 18083
' 0000 0001 1000 0000 1010 0011 --> 180A3
' 0000 0001 1000 0000 1100 0011 --> 180C3
'module: 0000 0001 1000 0000 0000 0001 --> 18001
' 0000 0001 1000 0000 0010 0001 --> 18021
'class: 0001 0001 1000 0000 0000 0011 --> 118003
' 0001 0011 1000 0000 0000 0011 --> 138003
' 0000 0001 1000 0000 0010 0011 --> 18023
' 0000 0001 1000 1000 0000 0011 --> 18803
' 0001 0001 1000 1000 0000 0011 --> 118803
'usercontrol: 0001 1101 1010 0000 0000 0011 --> 1DA003
' 0001 1101 1010 0000 0010 0011 --> 1DA023
' 0001 1101 1010 1000 0000 0011 --> 1DA803
'propertypage: 0001 0101 1000 0000 0000 0011 --> 158003
' | || | | | | |
'[moog] | || | | | | |
'HasPublicInterface ---+ || | | | | | (有公用的接口)
'HasPublicEvents --------+| | | | | | (有公用的事件)
'IsCreatable/Visible? ----+ | | | | | (是否可以创建,可见)
'Same as "HasPublicEvents" -----+ | | | |
'[aLfa] | | | | |
'usercontrol (1) ---------------+ | | | | (用户控制)
'ocx/dll (1) ----------------------+ | | | (OCX/DLL)
'form (1) ------------------------------+ | | (是不是FORM是就是1)
'vb5 (1) ---------------------------------+ | (是不是VB5是就是1)
'HasOptInfo (1) -------------------------------+ (有没有额外的信息信息由就是1,决定是不是指向OptionalObjectInfo_t类似与PEHEAD里的Optional信息一样)
' |
'module(0) ------------------------------------+ (如果是Module模块就这里是0)
typedef struct//这个是显示这个OBJECT信息的结构,每一个OBJECT都有一个
{
WORD Flag1;
WORD ObjectIndex;
DWORD aObjectTable;
DWORD Null1;
DWORD aSmallRecord; // when it is a module this value is -1 [better name?]
DWORD Const1;
DWORD Null2;
DWORD aObject;
DWORD RunTimeLoaded; //[can someone verify this?]
DWORD NumberOfProcs;
DWORD aProcTable;
WORD iConstantsCount; // Number of Constants
WORD iMaxConstants; // Maximum Constants to allocate.
DWORD Flag5;
WORD Flag6;
WORD Flag7;
WORD aConstantPool;
// sizeof() = 0x38
'the rest is optional items[OptionalObjectInfo]
}ObjectInfo_t;
Private Type tOptionalObjectInfo ' if ((tObject.ObjectType AND &H80)=&H80)
fDesigner As Long ' 0x00 (0d) If this value is 2 then this object is a designer
aObjectCLSID As Long ' 0x04
Null1 As Long ' 0x08
aGuidObjectGUI As Long ' 0x0C
lObjectDefaultIIDCount As Long ' 0x10 01 00 00 00
aObjectEventsIIDTable As Long ' 0x14
lObjectEventsIIDCount As Long ' 0x18
aObjectDefaultIIDTable As Long ' 0x1C
ControlCount As Long ' 0x20
aControlArray As Long ' 0x24
iEventCount As Integer ' 0x28 (40d) Number of Events
iPCodeCount As Integer ' 0x2C
oInitializeEvent As Integer ' 0x2C (44d) Offset to Initialize Event from aMethodLinkTable
oTerminateEvent As Integer ' 0x2E (46d) Offset to Terminate Event from aMethodLinkTable
aEventLinkArray As Long ' 0x30 Pointer to pointers of MethodLink
aBasicClassObject As Long ' 0x34 Pointer to an in-memory
Null3 As Long ' 0x38
Flag2 As Long ' 0x3C usually null
' 0x40 <-- Structure size
End Type
Type tProjectInfo2
lNull1 As Long ' 0x00 (00d)
aObjectTable As Long ' 0x04 (04d) Pointer to Object Table
lConst1 As Long ' 0x08 (08d)
lNull2 As Long ' 0x0C (12d)
aObjectDescriptorTable As Long ' 0x10 (16d) Pointer to a table of ObjectDescriptors
lNull3 As Long ' 0x14 (20d)
aNTSPrjDescription As Long ' 0x18 (24d) Pointer to Project Description
aNTSPrjHelpFile As Long ' 0x1C (28d) Pointer to Project Help File
lConst2 As Long ' 0x20 (32d)
lHelpContextID As Long ' 0x24 (36d) Project Help Context ID
' 0x28 (40d) <- Structure size
End Type
Type ObjectDescriptor
lNull1 As Long '0x00 (00d)
aObjectInfo As Long '0x04 (04d) Pointer to Object Info
lConst1 As Long '0x08 (08d)
lNull2 As Long '0x0C (12d)
lFlag1 As Long '0x10 (16d)
lNull3 As Long '0x14 (20d)
aUnknown1 As Long '0x18 (24d)
lNull4 As Long '0x1C (28d)
aUnknown2 As Long '0x20 (32d)
aUnknown3 As Long '0x24 (36d)
aUnknown4 As Long '0x28 (40d)
lNull5 As Long '0x2C (44d)
lNull6 As Long '0x30 (48d)
lNull7 As Long '0x34 (52d)
lFlag2 As Long '0x38 (56d)
fObjectType As Long '0x3C (60d) Flags for this Object
'0x40 (64d) <- Structure Size
End Type
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
未完待续!!!!!(还有很大大大大一部分类!!!)
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
[竞赛]2024 KCTF 大赛征题截止日期08月10日!