mirror of https://github.com/x64dbg/btparser
457 lines
12 KiB
Plaintext
457 lines
12 KiB
Plaintext
1:
|
|
2:
|
|
3:
|
|
4:
|
|
5:
|
|
6:
|
|
7:
|
|
8:
|
|
9:
|
|
10:
|
|
11:
|
|
12:
|
|
13:
|
|
14:
|
|
15: LittleEndian ( ) ;
|
|
16:
|
|
17: local const uint16 SignatureLen = 7 ;
|
|
18: const string RarSignature = "Rar!" + '\x1A' + '\x07' ;
|
|
19:
|
|
20:
|
|
21:
|
|
22: struct FileHeadBlock ;
|
|
23: struct OldCommentBlock ;
|
|
24: struct OldSubBlock ;
|
|
25: struct SubBlock ;
|
|
26:
|
|
27:
|
|
28:
|
|
29: enum < byte > RarBlockType
|
|
30: {
|
|
31: MARKER = 0x72 , ARCHIVE , FILE_OR_DIR , COMMENT_OLD , AV_OLD_1 , SUBBLOCK_OLD , RR_OLD , AV_OLD_2 , SUBBLOCK , _END_
|
|
32: } ;
|
|
33:
|
|
34:
|
|
35:
|
|
36: local uint16 _flags = 0 ;
|
|
37:
|
|
38:
|
|
39: local uquad iBlocksCounter = 0 ;
|
|
40: local uquad iFiles = 0 ;
|
|
41: local uquad iDirs = 0 ;
|
|
42: local uquad iComments = 0 ;
|
|
43: local uquad iSubBlocks = 0 ;
|
|
44: local uquad iUniNames = 0 ;
|
|
45: local uquad iBadCRCCounter = 0 ;
|
|
46: local ubyte iMinVerToUnpack = 0xFF ;
|
|
47: local ubyte iMaxVerToUnpack = 0 ;
|
|
48: local uquad iTotalUnpackedSize = 0 ;
|
|
49: local uint iAV1 = 0 ;
|
|
50: local uint iAV2 = 0 ;
|
|
51:
|
|
52:
|
|
53:
|
|
54: enum < ubyte > OsType
|
|
55: {
|
|
56: _MS_DOS , _OS_2 , _Win32 , _Unix , _Mac_OS , _BeOS
|
|
57: } ;
|
|
58:
|
|
59: enum < char > PackMethod
|
|
60: {
|
|
61: Store = '0' , Fastest , Fast , Normal , Good , Best
|
|
62: } ;
|
|
63:
|
|
64: enum < uint16 > SubType_OldStyle
|
|
65: {
|
|
66: OS2_EA = 0x100
|
|
67: } ;
|
|
68:
|
|
69: struct UnixStyleAttrs
|
|
70: {
|
|
71: uint32 owner_may_eXecute : 1 ;
|
|
72: uint32 owner_may_Write : 1 ;
|
|
73: uint32 owner_may_Read : 1 ;
|
|
74:
|
|
75: uint32 group_may_eXecute : 1 ;
|
|
76: uint32 gorup_may_Write : 1 ;
|
|
77: uint32 group_may_Read : 1 ;
|
|
78:
|
|
79: uint32 everybody_may_eXecute : 1 ;
|
|
80: uint32 everybody_may_Write : 1 ;
|
|
81: uint32 everybody_may_Read : 1 ;
|
|
82:
|
|
83: uint32 _s : 1 ;
|
|
84: uint32 _s : 1 ;
|
|
85:
|
|
86: uint32 _unused : 21 ;
|
|
87: } ;
|
|
88:
|
|
89: struct DosFileAttrs
|
|
90: {
|
|
91: uint32 READONLY : 1 ;
|
|
92: uint32 HIDDEN : 1 ;
|
|
93: uint32 SYSTEM : 1 ;
|
|
94: uint32 VOLUME : 1 ;
|
|
95: uint32 DIRECTORY : 1 ;
|
|
96: uint32 ARCHIVE : 1 ;
|
|
97: uint32 _res : 26 ;
|
|
98: } ;
|
|
99:
|
|
100: struct WinFileAttrs
|
|
101: {
|
|
102: uint32 READONLY : 1 ;
|
|
103: uint32 HIDDEN : 1 ;
|
|
104: uint32 SYSTEM : 1 ;
|
|
105: uint32 VOLUME : 1 ;
|
|
106: uint32 DIRECTORY : 1 ;
|
|
107: uint32 ARCHIVE : 1 ;
|
|
108: uint32 DEVICE : 1 ;
|
|
109: uint32 NORMAL : 1 ;
|
|
110: uint32 TEMPORARY : 1 ;
|
|
111: uint32 SPARSE_FILE : 1 ;
|
|
112: uint32 REPARSE_POINT : 1 ;
|
|
113: uint32 COMPRESSED : 1 ;
|
|
114: uint32 OFFLINE : 1 ;
|
|
115: uint32 NOT_CONTENT_INDEXED : 1 ;
|
|
116: uint32 ENCRYPTED : 1 ;
|
|
117: uint32 _res2 : 17 ;
|
|
118: } ;
|
|
119:
|
|
120: struct CommonBlockFlags
|
|
121: {
|
|
122: ushort _reserved : 14 ;
|
|
123: ushort OLD_VERSION_IGNORE : 1 ;
|
|
124: ushort ADD_SIZE_PRESENT : 1 ;
|
|
125: } ;
|
|
126:
|
|
127: struct MainHeadFlags
|
|
128: {
|
|
129: ubyte ARCHIVE_VOLUME : 1 ;
|
|
130: ubyte ARCHIVE_COMMENT_PRESENT : 1 ;
|
|
131: ubyte ARCHIVE_LOCKED : 1 ;
|
|
132: ubyte ARCHIVE_SOLID : 1 ;
|
|
133: ubyte NEW_VOLUME_NAMING : 1 ;
|
|
134: ubyte AV_PRESENT : 1 ;
|
|
135: ubyte RECOVERY_PRESENT : 1 ;
|
|
136: ubyte BLOCK_HEADERS_ENCRYPTED : 1 ;
|
|
137: ubyte IS_FIRST_VOLUME : 1 ;
|
|
138: ubyte _reserved : 5 ;
|
|
139: ubyte OLD_VERSION_IGNORE : 1 ;
|
|
140: ubyte ADD_SIZE_PRESENT : 1 ;
|
|
141: } ;
|
|
142:
|
|
143:
|
|
144: enum < byte > FileDictType
|
|
145: {
|
|
146: _64K , _128K , _256K , _512K , _1024K , _2048K , _4096K , _Directory
|
|
147: } ;
|
|
148:
|
|
149: struct FileHeadFlags
|
|
150: {
|
|
151: ubyte from_PREV_VOLUME : 1 ;
|
|
152: ubyte to_NEXT_VOLUME : 1 ;
|
|
153: ubyte PASSWORD_ENCRYPTED : 1 ;
|
|
154: ubyte FILE_COMMENT_PRESENT : 1 ;
|
|
155: ubyte SOLID : 1 ;
|
|
156: FileDictType DICTIONARY : 3 ;
|
|
157: ubyte HIGH_SIZE : 1 ;
|
|
158: ubyte has_UNICODE_FILENAME : 1 ;
|
|
159: ubyte ENCRYPTION_SALT : 1 ;
|
|
160: ubyte IS_OLD_FILE_VERSION : 1 ;
|
|
161: ubyte EXTENDED_TIME_INFO : 1 ;
|
|
162: ubyte _reserved : 1 ;
|
|
163: ubyte OLD_VERSION_IGNORE : 1 ;
|
|
164: ubyte ADD_SIZE_PRESENT : 1 ;
|
|
165: } ;
|
|
166:
|
|
167: struct RarBlock
|
|
168: {
|
|
169: local quad iOfs = FTell ( ) ;
|
|
170:
|
|
171: uint16 HEAD_CRC < format = hex , fgcolor = cRed > ;
|
|
172:
|
|
173: RarBlockType HeadType < fgcolor = cGreen > ;
|
|
174:
|
|
175: _flags = ReadUShort ( FTell ( ) ) ;
|
|
176:
|
|
177: if ( HeadType == ARCHIVE )
|
|
178: MainHeadFlags HEAD_FLAGS ;
|
|
179: else if ( HeadType == FILE_OR_DIR )
|
|
180: FileHeadFlags HEAD_FLAGS ;
|
|
181: else
|
|
182: CommonBlockFlags HEAD_FLAGS ;
|
|
183:
|
|
184: ++ iBlocksCounter ;
|
|
185:
|
|
186: if ( HeadType < MARKER || HeadType > _END_ )
|
|
187: {
|
|
188: Warning ( "Unknown Header Type (0x%02x) in Block #%Lu" , HeadType , iBlocksCounter ) ;
|
|
189: Printf ( "Unknown Header Type (0x%02x) in Block #%Lu\n" , HeadType , iBlocksCounter ) ;
|
|
190: }
|
|
191:
|
|
192: uint16 HeaderSize ;
|
|
193:
|
|
194: if ( HeaderSize < 7 )
|
|
195: {
|
|
196: Warning ( "Invalid block size (%u) in Block #%Lu" , HeaderSize , iBlocksCounter ) ;
|
|
197: Printf ( "Invalid block size (%u) in Block #%Lu\n" , HeaderSize , iBlocksCounter ) ;
|
|
198: return - 1 ;
|
|
199: }
|
|
200:
|
|
201: if ( HeadType != MARKER )
|
|
202: {
|
|
203: local uint16 crcCheck = Checksum ( CHECKSUM_CRC32 , startof ( HeadType ) , HeaderSize - sizeof ( HEAD_CRC ) ) & 0xFFFF ;
|
|
204: if ( crcCheck != HEAD_CRC )
|
|
205: {
|
|
206: Warning ( "Header CRC mismatch in Block #%Lu" , iBlocksCounter ) ;
|
|
207: Printf ( "Header CRC mismatch in Block #%Lu: expected CRC is 0x%X, got 0x%X\n" , iBlocksCounter , crcCheck , HEAD_CRC ) ;
|
|
208: ++ iBadCRCCounter ;
|
|
209: }
|
|
210: }
|
|
211:
|
|
212: if ( HEAD_FLAGS . ADD_SIZE_PRESENT )
|
|
213: uint32 RawDataSize ;
|
|
214: else
|
|
215: local uint32 RawDataSize = 0 ;
|
|
216:
|
|
217: switch ( HeadType ) {
|
|
218: case ARCHIVE :
|
|
219: uint16 _reserved1 ;
|
|
220: uint32 _reserved2 ;
|
|
221: if ( HEAD_FLAGS . ARCHIVE_COMMENT_PRESENT ) struct RarBlock MainComment ;
|
|
222: break ;
|
|
223: case FILE_OR_DIR :
|
|
224: if ( HEAD_FLAGS . DICTIONARY == 7 )
|
|
225: {
|
|
226: ++ iDirs ;
|
|
227: FileHeadBlock dir ;
|
|
228: }
|
|
229: else
|
|
230: {
|
|
231: ++ iFiles ;
|
|
232: FileHeadBlock file ;
|
|
233: }
|
|
234: break ;
|
|
235: case COMMENT_OLD :
|
|
236: OldCommentBlock cmm ;
|
|
237: break ;
|
|
238: case SUBBLOCK_OLD :
|
|
239: OldSubBlocksub ;
|
|
240: break ;
|
|
241: case SUBBLOCK :
|
|
242: SubBlock sub ;
|
|
243: break ;
|
|
244: case AV_OLD_1 :
|
|
245: ++ iAV1 ;
|
|
246: Printf ( "*** AV was found (RAR v. < 2.60) @ block #%Lu.\n" , iBlocksCounter ) ;
|
|
247: break ;
|
|
248: case AV_OLD_2 :
|
|
249: ++ iAV2 ;
|
|
250: Printf ( "*** AV was found (RAR v. 2.60 - 2.9x) @ block #%Lu.\n" , iBlocksCounter ) ;
|
|
251: break ;
|
|
252: }
|
|
253:
|
|
254: iOfs = HeaderSize - ( FTell ( ) - iOfs ) ;
|
|
255:
|
|
256: if ( iOfs > 0 )
|
|
257: ubyte _reserved [ iOfs ] ;
|
|
258:
|
|
259: if ( RawDataSize > 0 )
|
|
260: ubyte _raw [ RawDataSize ] < format = hex , fgcolor = cBlue > ;
|
|
261: } ;
|
|
262:
|
|
263: struct FileHeadBlock
|
|
264: {
|
|
265: uint32 UnpackedSize ;
|
|
266: iTotalUnpackedSize += UnpackedSize ;
|
|
267:
|
|
268: OsType Host_OS ;
|
|
269: uint32 FileCRC32 < format = hex > ;
|
|
270: DOSTIME FileTime ;
|
|
271: DOSDATE FileDate ;
|
|
272: ubyte VersionToUnpack ;
|
|
273:
|
|
274: if ( VersionToUnpack > iMaxVerToUnpack )
|
|
275: iMaxVerToUnpack = VersionToUnpack ;
|
|
276:
|
|
277: if ( VersionToUnpack < iMinVerToUnpack )
|
|
278: iMinVerToUnpack = VersionToUnpack ;
|
|
279:
|
|
280: PackMethod Method ;
|
|
281: uint16 NameSize ;
|
|
282:
|
|
283: switch ( Host_OS ) {
|
|
284: case _Win32 :
|
|
285: WinFileAttrs Attributes ;
|
|
286: break ;
|
|
287: case _MS_DOS :
|
|
288: case _Mac_OS :
|
|
289: case _OS_2 :
|
|
290: DosFileAttrs Attributes ;
|
|
291: break ;
|
|
292: case _Unix :
|
|
293: case _BeOS :
|
|
294: UnixStyleAttrs Attributes ;
|
|
295: break ;
|
|
296: default :
|
|
297: uint32 Attributes < format = binary > ;
|
|
298: }
|
|
299:
|
|
300: if ( _flags & 0x100 )
|
|
301: {
|
|
302: uint32 HIGH_PACK_SIZE ;
|
|
303: uint32 HIGH_UNP_SIZE ;
|
|
304:
|
|
305: iTotalUnpackSize += ( HIGH_UNP_SIZE << 32 ) ;
|
|
306: }
|
|
307:
|
|
308: if ( _flags & 0x200 )
|
|
309: {
|
|
310: ++ iUniNames ;
|
|
311:
|
|
312: string FileName ;
|
|
313: uint16 WideFileNameData [ ( NameSize - sizeof ( FileName ) ) / 2 ] ;
|
|
314: }
|
|
315: else
|
|
316: char FileName [ NameSize ] ;
|
|
317:
|
|
318: if ( _flags & 0x8 )
|
|
319: {
|
|
320: RarBlock FileComment ;
|
|
321: }
|
|
322:
|
|
323: if ( _flags & 0x400 )
|
|
324: uquad SALT < format = hex > ;
|
|
325: } ;
|
|
326:
|
|
327:
|
|
328:
|
|
329: struct OldCommentBlock {
|
|
330: ++ iComments ;
|
|
331:
|
|
332: uint16 UnpackedSize ;
|
|
333: ubyte VersionToUnpack ;
|
|
334: PackMethod Method ;
|
|
335: uint16 CommentCRC < format = hex > ;
|
|
336:
|
|
337: Printf ( "*** Old style CommentBlock: (Block #%Lu)\n" , iBlocksCounter ) ;
|
|
338: } ;
|
|
339:
|
|
340: struct OldSubBlock {
|
|
341: ++ iSubBlocks ;
|
|
342:
|
|
343: SubType_OldStyle SubType ;
|
|
344: ubyte _reserved ;
|
|
345:
|
|
346: Printf ( "*** Old style SubBlock: %u (Block #%Lu)\n" , SubType , iBlocksCounter ) ;
|
|
347: } ;
|
|
348:
|
|
349: struct SubBlock {
|
|
350: ++ iSubBlocks ;
|
|
351:
|
|
352: ubyte _unknown_to_me_1 [ 15 ] ;
|
|
353: ubyte SubTypeLen ;
|
|
354: ubyte _unknown_to_me_2 [ 5 ] ;
|
|
355: char SubType [ SubTypeLen ] ;
|
|
356:
|
|
357: Printf ( "*** SubBlock: %s (Block #%Lu)\n" , SubType + '\0' , iBlocksCounter ) ;
|
|
358: switch ( SubType ) {
|
|
359: case "CMT" :
|
|
360: ++ iComments ;
|
|
361: break ;
|
|
362: case "AV" :
|
|
363: Printf ( "*** Authenticity Verification info (RAR v. 3.x) @ block #%Lu.\n" , iBlocksCounter ) ;
|
|
364: break ;
|
|
365: case "RR" :
|
|
366: Printf ( "*** Recovery Record was found (RAR v. 3.x) @ block #%Lu.\n" , iBlocksCounter ) ;
|
|
367: break ;
|
|
368: }
|
|
369: } ;
|
|
370:
|
|
371:
|
|
372:
|
|
373: local string fn = GetFileName ( ) ;
|
|
374: local quad SignaturePos = 0 ;
|
|
375: local char Signature [ SignatureLen ] ;
|
|
376:
|
|
377: if ( Strstr ( fn , ".rar" ) != Strlen ( fn ) - 4 )
|
|
378: {
|
|
379: Warning ( "Seeking for RAR signature..." ) ;
|
|
380:
|
|
381: local quad _p = FindFirst ( RarSignature ) ;
|
|
382: if ( _p >= 0 )
|
|
383: FSeek ( _p ) ;
|
|
384: else
|
|
385: {
|
|
386: Warning ( "Not a RAR archive!" ) ;
|
|
387: return - 1 ;
|
|
388: }
|
|
389:
|
|
390: Warning ( "RAR signature found at 0x%08x." , _p ) ;
|
|
391: Printf ( "RAR signature found at 0x%08x.\n" , _p ) ;
|
|
392: }
|
|
393: else
|
|
394: {
|
|
395: ReadBytes ( Signature , SignaturePos , SignatureLen ) ;
|
|
396:
|
|
397: if ( Strcmp ( Signature , RarSignature ) )
|
|
398: {
|
|
399: Warning ( "Invalid RAR Archive Signature!" ) ;
|
|
400: return SignaturePos ;
|
|
401: }
|
|
402: }
|
|
403:
|
|
404: RarBlock Marker ;
|
|
405:
|
|
406: RarBlock ArcHeader ;
|
|
407: if ( ArcHeader . HeadType != ARCHIVE )
|
|
408: {
|
|
409: Warning ( "Main archive header is either bad or missing!" ) ;
|
|
410: return - 2 ;
|
|
411: }
|
|
412: else
|
|
413: {
|
|
414: Printf ( "It is a %s%s %s %s RAR archive.\n" ,
|
|
415: SignaturePos > 0 ? "SelF-eXtractable " : "" ,
|
|
416: ArcHeader . HEAD_FLAGS . ARCHIVE_LOCKED ? "LOCKED" : "non-locked" ,
|
|
417: ArcHeader . HEAD_FLAGS . ARCHIVE_SOLID ? "SOLID" : "regular" ,
|
|
418: ArcHeader . HEAD_FLAGS . ARCHIVE_VOLUME ? "VOLUME'd" : "one-part" ) ;
|
|
419:
|
|
420: if ( ArcHeader . HEAD_FLAGS . ARCHIVE_COMMENT_PRESENT )
|
|
421: Printf ( "Main comment is present.\n" ) ;
|
|
422: if ( ArcHeader . HEAD_FLAGS . AV_PRESENT )
|
|
423: Printf ( "Old style Authenticity Verification is present.\n" ) ;
|
|
424: if ( ArcHeader . HEAD_FLAGS . RECOVERY_PRESENT )
|
|
425: Printf ( "Recovery Record is present.\n" ) ;
|
|
426:
|
|
427: if ( ArcHeader . HEAD_FLAGS . BLOCK_HEADERS_ENCRYPTED )
|
|
428: {
|
|
429: Printf ( "It's an encrypted archive. Cannot proceed, exiting...\n" ) ;
|
|
430: return - 3 ;
|
|
431: }
|
|
432: }
|
|
433:
|
|
434: while ( ! FEof ( ) )
|
|
435: {
|
|
436: RarBlock block ;
|
|
437: }
|
|
438:
|
|
439: if ( block . HeadType != _END_ && iMaxVerToUnpack > 20 )
|
|
440: {
|
|
441: Warning ( "END Marker block was expected here." ) ;
|
|
442: }
|
|
443:
|
|
444: if ( iFiles || iDirs )
|
|
445: {
|
|
446: Printf ( "Version to unpack: %u.%u\n" , iMaxVerToUnpack / 10 , iMaxVerToUnpack % 10 ) ;
|
|
447: if ( iMinVerToUnpack != iMaxVerToUnpack )
|
|
448: Printf ( "Some data can also be retrieved by an earlier version of %u.%u\n" ,
|
|
449: iMinVerToUnpack / 10 , iMinVerToUnpack % 10 ) ;
|
|
450: }
|
|
451:
|
|
452: Printf ( "Files: %Lu, Dirs: %Lu, Comments: %Lu, SubBlocks: %Lu, Unpacked Size: %Lu\n" , iFiles , iDirs , iComments , iSubBlocks , iTotalUnpackedSize ) ;
|
|
453: Printf ( "UNICODE Names: %Lu\n" , iUniNames ) ;
|
|
454: if ( iBadCRCCounter )
|
|
455: Printf ( "%Lu blocks corrupted.\n" , iBadCRCCounter ) ;
|
|
456: Printf ( "Done. %Lu blocks processed.\n" , iBlocksCounter ) ;
|
|
457: tok_eof |