DWG 2004 格式解析系列(二)文件结构

您所在的位置:网站首页 dwg文件怎么看 DWG 2004 格式解析系列(二)文件结构

DWG 2004 格式解析系列(二)文件结构

2023-10-01 02:11| 来源: 网络整理| 查看: 265

目录

0  总体结构

1  文件头

2  数据

2.1 system section

a) system section page header

b) Section Map page data

c) SectionInfo page data

2.2 Data section

0   总体结构

        从整体上看,一个dwg文件可分为2部分:文件头和数据,数据部分在物理上分页(page)存储的,在逻辑上由一个或多个页组成一个段(section),如图所示:

1  文件头

        文件头长度为0x100个字节,布局如下:

地址

长度(byte)

描述

0x00

7

"AC1018\0"

0x07

4

0x00

0x0B

1

主版本号

0x0C

1

0x00或0x01或0x03

0x0D

4

预览图片的地址

0x11

1

Dwg version

0x12

1

Dwg maintance version

0x13

2

Codepage index

0x15

1

0x00

0x16

1

App version

0x17

1

App maintance version

0x18

4

安全标志

0x0001:加密数据(除了AcDb:Preview and AcDb:SummaryInfo)

0x0002:加密属性(用于AcDb:Preview and AcDb:SummaryInfo)

0x0010:sign data

0x0020:add timestamp

0x1C

4

未知

0x20

4

SummaryInfo地址,points to summary info page + page header size(0x20)

0x24

4

VBA工程地址

0x28

4

0x00000080,(似乎是2004header的地址)

0x2C

0x54

全是0x00

0x80

0x6C

加密的数据,称为2004header

0xEC

0x14

填充数据(据说是魔术字节序列的前0x14字节,未做考证)

开始的7个字节是DWG版本标志串,以AC开头,后跟4个数字表述版本。对应关系为:

标注串AutoCAD的发行版本AC1012R13AC1014R14AC10152000 - 2003AC10182004 - 2006AC10212007 - 2009AC10242010 - 2012AC10272013 - 2017AC10322018 - 2020

从AutoCAD2000开始,dwg版本号每3年做一次升级,所以AC标志串中的数字并不是连续的。

 0x80处的0x6C个字节的加密数据,与下列0x6C个魔术字节逐一做XOR运算,即可解密。

29 23 BE 84 E1 6C D6 AE    52 90 49 F1 F1 BB E9 EB B3 A6 DB 3C 87 0C 3E 99    24 5E 0D 1C 06 B7 47 DE B3 12 4D C8 43 BB 8B A6    1F 03 5A 7D 09 38 25 1F 5D D4 CB FC 96 F5 45 3B    13 0D 89 0A 1C DB AE 32 20 9A 50 EE 40 78 36 FD    12 49 32 F6 9E 7D 49 DC AD 4F 14 F2 44 40 66 D0    6B C4 30 B7 32 3B A1 22 F6 22 91 9D E1 8B 1F DA    B0 CA 99 02

这0x6C个魔术字节可以用下面的代码得到

unsigned char pc[0x6c]; int randseed = 1; for (int i=0; i>0x10); }

经过以上运算解密后的数据布局如下表,称之为ACAD2004HeaderData,这段数据在文件尾部还有一份,即SecondHeaderData。

字地址

长度(byte)

描述

0x00

12

"AcFssFcAJMB\0" 标志串

0x0C

4

0x00 (long) header address

0x10

4

0x6c(long) header size

0x14

4

0x04 (long)

0x18

4

Root tree node gap

0x1C

4

Lowermost left tree node gap

0x20

4

Lowermost right tree node gap

0x24

4

未知(long)

0x28

4

Last section id

0x2C

4

Last section address

0x30

4

0x00

0x34

4

Second header address

0x38

4

0x00

0x3C

4

Gap 总数

0x40

4

Section总数

0x44

4

0x20 (long)

0x48

4

0x80(long)

0x4C

4

0x40(long)

0x50

4

Page Map Id

0x54

4

Page Map Address

该值是以数据部分为起点的偏移,在整个文件中的偏移需要加上文件头的大小(0x100)

0x58

4

0x00

0x5C

4

Section map Id

0x60

4

Section page array size

0x64

4

Gap array size

0x68

4

CRC32 (long)

在这些数据当中,对解析最重要的当属标红的3个数据了。

(5.25,补充一下文件头的解析)

解析2004的文件头比较简单,只需要很少的代码。先定义如下的文件头结构:

#pragma pack(push, 1) typedef struct _tagDwg2004Header { // 务必保持成员的顺序! char version[7]; // 0x00: "AC1018\0" char x07_unknown_0[4]; // 0x07: 4zeros char is_maint; // 0x0B char x0c_0_1_3; // 0x0C: 0 or 1 or 3 uint32_t thumbnail_addr; // 0x0D char dwg_version; // 0x11 char dwg_maint_version; // 0x12 short codepage; // 0x13 char x15_unknown_0; // 0x15 char app_version; // 0x16 char app_maint_version; // 0x17 uint32_t security_type; // 0x18 uint32_t x1c_unknown_0; // 0x1C uint32_t summary_info_address; // 0x20 uint32_t vba_proj_address; // 0x24 uint32_t r2004_header_address; // 0x28: 0x80 char x2c_0[0x54]; // 0x2C: 0 union { char encrypted_data[0x6c]; // 0x80 struct _r2004 { char file_id_string[12]; // "AcFssFcAJMB\0" uint32_t header_address; // 0x00 uint32_t header_size; // 0x6c uint32_t x14_unknown_0; // 0 uint32_t root_tree_node_gap; uint32_t lowermost_left_tree_node_gap; uint32_t lowermost_right_tree_node_gap; uint32_t x24_uknown; uint32_t last_section_id; uint64_t last_page_address; uint64_t second_header_address; uint32_t gap_amount; uint32_t page_amount; uint32_t x44_x20; uint32_t x48_x80; uint32_t x4c_x40; uint32_t page_map_id; uint64_t page_map_address; // offset from DATA, not include this HEADER size uint32_t section_map_id; uint32_t section_array_size; uint32_t gap_array_size; uint32_t crc32; } r2004; }; char padding[0x14]; } Dwg2004Header; // total 0x100 bytes #pragma pack(pop)

 解析的代码:

{ // 说明:m_header的类型是上面定义的Dwg2004Header,DWG_DATA是dwg文件的原始数据 memcpy(&m_header, DWG_DATA, sizeof(Dwg2004Header)); // decrypt r2004 header int rseed = 1; for (int i = 0; i < 0x6c; i++) { rseed *= 0x343fd; rseed += 0x269ec3; m_header.encrypted_data[i] ^= (rseed >> 0x10); } } 2   数据

dwg的数据是分段(section)组织的,文件中涉及到的数据段有:

/// \enum Section type of R2004+ typedef enum _tagDwg2004SectionType { SECTION_UNKNOWN = 0, ///< The very first 160 byte SECTION_HEADER = 1, ///< AcDb:Header SECTION_AUXHEADER = 2, ///< AcDb:AuxHeader SECTION_CLASSES = 3, ///< AcDb:Classes SECTION_HANDLES = 4, ///< AcDb:Handles SECTION_TEMPLATE = 5, ///< AcDb:Template SECTION_OBJFREESPACE = 6, ///< AcDb:ObjFreeSpace SECTION_OBJECTS = 7, ///< AcDb:AcDbObjects SECTION_REVHISTORY = 8, ///< AcDb:RevHistory SECTION_SUMMARYINFO = 9, ///< AcDb:SummaryInfo SECTION_PREVIEW = 10, ///< AcDb:Preview SECTION_APPINFO = 11, ///< AcDb:AppInfo SECTION_APPINFOHISTORY = 12, ///< AcDb:AppInfoHistory SECTION_FILEDEPLIST = 13, ///< AcDb:FileDepList SECTION_SECURITY, ///< AcDb:Security, if stored with a password SECTION_VBAPROJECT, ///< AcDb:VBAProject SECTION_SIGNATURE, ///< AcDb:Signature SECTION_ACDS, ///< AcDb:AcDsPrototype_1b = 12 (ACIS datastorage) SECTION_SECTIONMAP, ///< system section: section map SECTION_PAGEMAP, ///< system section: page map } Dwg2004SectionType;

        所有的section中,page map段和section map段,这2个section至关重要,必须先根据ACAD2004HeaderData中标红的三个参数从文件中读取,再根据读到的结果,一一读取不同的数据段予以解析。

        首先从page map address处读取pagen map,然后从此map中取得section map Id对应的段(即section map section)的地址,并从文件中读出它的数据。这两种section统称为system section,其他的section则称为data section。之后,由这两兄弟配合就可以通过section name确定各种section的数据页在文件中的位置,根据描述信息予以读取。

        system section都只有一页,而data section 至少有一页。

2.1 system section

system section的数据是按页(page)组织的。一个page包含2部分,页头和页数据:

项目

长度

header

0x14bytes

data

压缩数据,长度由header.CompDataSize指定

其中header对于两种system section来说,结构是一样的,差别在于data的结构的不同。

a) system section page header

Header的结构:

地址(偏移)

长度(byte)

含义

0x00

4

Page 类型,有2种system page:

page map page: 0x41630e3b

section map page: 0x4163003b

0x04

4

解压后的数据长度 (DecompDataSize)

0x08

4

压缩后的数据长度 (CompDataSize)

0x0C

4

压缩类型(0x02)

0x10

4

CRC

当 page.CompDataSize==0时,这个system section就结束了,后面也不会再跟随page data。如下图所示就是system section的组织形式:

b) Page Map page data

page map段的页数据经解压缩后,为多个(page number, page size)数据对,其中的page number从1开始计数,该数据对记录的是文件中的各数据页的编号和大小。

地址

长度

描述

0x00

4

page number, 1-based

0x04

4

page size

这种数据对一直重复,直到本页的数据耗尽。在读取时,可以顺便计算出各section在文件中的绝对偏移地址:第一个读到的section的地址总是从文件头后(即0x100处)开始,后续读到的section的偏移可从其前一个section的偏移和大小计算得到。

c) Section Mappage data

从上面的pagemap只能得到已知某个编号的page的位置和大小,无法得到该page的具体信息,包括压缩否,加密否等等,这时就该section map上场了。section map的page.data解压缩后的布局如下,这是一个复合结构:

偏移

长度

含义

0x00

4

Number of descriptions(num_descs)

0x04

4

Compressed?(1=no, 2=yes, normally 2)

0x08

4

Max_size(normally 0x7400)

0x0C

4

Excrypted?(0=no, 1=yes, 2=unknown)

0x10

4

Num descriptions 2

共有num_descs组

0x00

8

Size of section

0x08

4

Number of pages(num_pages)

0x0C

4

Max decompress size

0x10

4

未知(会不会是long型的Max decompress size的高位?)

0x14

4

Compressed?(1=no,2=yes,normally 2)

0x18

4

Section type

0x1C

4

Encrypted?(0=no,1=yes,2=unknow)

0x20

64

Section name ("AcDbObjects"等等)

共有

num_pages组

0x00

4

page number

0x04

4

page data size

0x08

8

Start offset

对system section的归纳图示:

下面是一个解析实例中,关于AcDbObjects的section map的描述。

Description No.7 ------------------ size: 0x2b0e9 num_pages: 0x6 max_decomp_size: 0x7400 unknown2: 0x1 compressed: 0x2 type: 0x7 encrypted: 0x0 name: AcDb:AcDbObjects No.1 ............. page number: 6 data size: 0x30ea offset: 0x0 unknown: 0x0 No.2 ............. page number: 7 data size: 0x7f0 offset: 0x7400 No.3 ............. number: 8 data size: 0x628 offset: 0xe800 No.4 ............. page number: 9 data size: 0xf1f offset: 0x15c00 No.5 ............. page number: 10 data size: 0xcc0 offset: 0x1d000 No.6 ............. page number: 11 data size: 0xe0c offset: 0x24400 2.2 Data section page

data section page的布局为:

项目

长度

含义

Header

0x20

加密头

Data

DataSize

数据

Padding

page size

- DataSzie

-0x20

填充

 对加密头解密后的数据结构为:

偏移

长度

含义

0x00

4

Tag of data section (0x4163043B)

0x04

4

Section type

0x08

4

DataSize, Data的长度

0x0C

4

page size 本page的总长度(包括header,data和padding)

0x10

8

offset,Data解压后在解压缓冲中的存放偏移

0x18

4

Check sum 1

0x1C

4

Check sum 2

加密头的解密方法:

假设0x20长度的头数据存放在header[8]中,offset是本page在dwg文件中的绝对偏移,可从page map中得到。

int32_t header[8]; int32_t mask = 0x4164536b ^ offset; for (int i=0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3