Rizin
unix-like reverse engineering framework and cli tools
cabinfo.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "mspack/mspack.h"
#include "mspack/macros.h"
#include "mspack/cab.h"

Go to the source code of this file.

Macros

#define FSEEK   fseek
 
#define FTELL   ftell
 
#define FILELEN   long
 
#define MIN(a, b)   ((a)<(b)?(a):(b))
 
#define GETOFFSET   (FTELL(fh))
 
#define READ(buf, len)   if (myread((void *)(buf),(len))) return
 
#define SKIP(offset)   if (FSEEK(fh,(offset),SEEK_CUR)) return
 
#define SEEK(offset)   if (FSEEK(fh,(offset),SEEK_SET)) return
 
#define SEARCH_SIZE   (32*1024)
 
#define GETLONG(n)   EndGetI32(&buf[n])
 
#define GETWORD(n)   EndGetI16(&buf[n])
 
#define GETBYTE(n)   ((int)buf[n])
 
#define CAB_NAMEMAX   (1024)
 

Functions

void search ()
 
void getinfo (FILELEN base_offset)
 
char * read_name ()
 
int main (int argc, char *argv[])
 
int myread (void *buf, size_t length)
 

Variables

FILE * fh
 
char * filename
 
FILELEN filelen
 
unsigned char search_buf [SEARCH_SIZE]
 
char namebuf [CAB_NAMEMAX]
 

Macro Definition Documentation

◆ CAB_NAMEMAX

#define CAB_NAMEMAX   (1024)

Definition at line 330 of file cabinfo.c.

◆ FILELEN

#define FILELEN   long

Definition at line 45 of file cabinfo.c.

◆ FSEEK

#define FSEEK   fseek

Definition at line 43 of file cabinfo.c.

◆ FTELL

#define FTELL   ftell

Definition at line 44 of file cabinfo.c.

◆ GETBYTE

#define GETBYTE (   n)    ((int)buf[n])

Definition at line 175 of file cabinfo.c.

◆ GETLONG

#define GETLONG (   n)    EndGetI32(&buf[n])

Definition at line 173 of file cabinfo.c.

◆ GETOFFSET

#define GETOFFSET   (FTELL(fh))

Definition at line 79 of file cabinfo.c.

◆ GETWORD

#define GETWORD (   n)    EndGetI16(&buf[n])

Definition at line 174 of file cabinfo.c.

◆ MIN

#define MIN (   a,
  b 
)    ((a)<(b)?(a):(b))

Definition at line 78 of file cabinfo.c.

◆ READ

#define READ (   buf,
  len 
)    if (myread((void *)(buf),(len))) return

Definition at line 80 of file cabinfo.c.

◆ SEARCH_SIZE

#define SEARCH_SIZE   (32*1024)

Definition at line 88 of file cabinfo.c.

◆ SEEK

#define SEEK (   offset)    if (FSEEK(fh,(offset),SEEK_SET)) return

Definition at line 82 of file cabinfo.c.

◆ SKIP

#define SKIP (   offset)    if (FSEEK(fh,(offset),SEEK_CUR)) return

Definition at line 81 of file cabinfo.c.

Function Documentation

◆ getinfo()

void getinfo ( FILELEN  base_offset)

Definition at line 177 of file cabinfo.c.

177  {
178  unsigned char buf[64];
179  int header_res = 0, folder_res = 0, data_res = 0;
180  int num_folders, num_files, flags, i, j;
181  FILELEN files_offset, min_data_offset = filelen;
182 
183  SEEK(base_offset);
185 
186  files_offset = base_offset + GETLONG(cfhead_FileOffset);
187  num_folders = GETWORD(cfhead_NumFolders),
188  num_files = GETWORD(cfhead_NumFiles),
190 
191  printf("CABINET HEADER @%"LD":\n", base_offset);
192  printf("- signature = '%4.4s'\n", buf);
193  printf("- overall length = %u bytes\n", GETLONG(cfhead_CabinetSize));
194  printf("- files offset = %"LD"\n", files_offset);
195  printf("- format version = %d.%d\n",
197  printf("- folder count = %u\n", num_folders);
198  printf("- file count = %u\n", num_files);
199  printf("- header flags = 0x%04x%s%s%s\n", flags,
200  ((flags & cfheadPREV_CABINET) ? " PREV_CABINET" : ""),
201  ((flags & cfheadNEXT_CABINET) ? " NEXT_CABINET" : ""),
202  ((flags & cfheadRESERVE_PRESENT) ? " RESERVE_PRESENT" : ""));
203  printf("- set ID = %u\n", GETWORD(cfhead_SetID));
204  printf("- set index = %u\n", GETWORD(cfhead_CabinetIndex));
205 
208  header_res = GETWORD(cfheadext_HeaderReserved);
209  folder_res = GETBYTE(cfheadext_FolderReserved);
210  data_res = GETBYTE(cfheadext_DataReserved);
211  printf("- header reserve = %u bytes (@%"LD")\n",
212  header_res, GETOFFSET);
213  printf("- folder reserve = %u bytes\n", folder_res);
214  printf("- data reserve = %u bytes\n", data_res);
215  SKIP(header_res);
216  }
217  if (flags & cfheadPREV_CABINET) {
218  printf("- prev cabinet = %s\n", read_name());
219  printf("- prev disk = %s\n", read_name());
220  }
221  if (flags & cfheadNEXT_CABINET) {
222  printf("- next cabinet = %s\n", read_name());
223  printf("- next disk = %s\n", read_name());
224  }
225 
226  printf("FOLDERS SECTION @%"LD":\n", GETOFFSET);
227  for (i = 0; i < num_folders; i++) {
228  FILELEN folder_offset, data_offset;
229  int comp_type, num_blocks, offset_ok;
230  char *type_name;
231 
232  folder_offset = GETOFFSET;
234  data_offset = base_offset + GETLONG(cffold_DataOffset);
235  num_blocks = GETWORD(cffold_NumBlocks),
236  comp_type = GETWORD(cffold_CompType);
237 
238  min_data_offset = MIN(data_offset, min_data_offset);
239  offset_ok = data_offset < filelen;
240 
241  switch (comp_type & cffoldCOMPTYPE_MASK) {
242  case cffoldCOMPTYPE_NONE: type_name = "stored"; break;
243  case cffoldCOMPTYPE_MSZIP: type_name = "MSZIP"; break;
244  case cffoldCOMPTYPE_QUANTUM: type_name = "Quantum"; break;
245  case cffoldCOMPTYPE_LZX: type_name = "LZX"; break;
246  default: type_name = "unknown"; break;
247  }
248 
249  printf("- folder 0x%04x @%"LD" %u data blocks @%"LD"%s %s compression (0x%04x)\n",
250  i, folder_offset, num_blocks, data_offset,
251  offset_ok ? "" : " [INVALID OFFSET]",
252  type_name, comp_type);
253 
254  SEEK(data_offset);
255  for (j = 0; j < num_blocks; j++) {
256  int clen, ulen;
257  if (GETOFFSET > filelen) {
258  printf(" - datablock %d @%"LD" [INVALID OFFSET]\n", j, GETOFFSET);
259  break;
260  }
264  printf(" - datablock %d @%"LD" csum=%08x c=%5u u=%5u%s\n",
265  j, data_offset, GETLONG(cfdata_CheckSum), clen, ulen,
266  ((clen > (32768+6144)) || (ulen > 32768)) ? " INVALID" : "");
267  data_offset += cfdata_SIZEOF + data_res + clen;
268  SKIP(data_res + clen);
269  }
270  SEEK(folder_offset + cffold_SIZEOF + folder_res);
271  }
272 
273  printf("FILES SECTION @%"LD":\n", GETOFFSET);
274  if (files_offset != GETOFFSET) {
275  printf("INVALID: file offset in header %"LD
276  " doesn't match start of files %"LD"\n",
277  files_offset, GETOFFSET);
278  }
279 
280  for (i = 0; i < num_files; i++) {
281  FILELEN file_offset = GETOFFSET;
282  char *folder_type;
283  int attribs, folder;
284 
285  if (file_offset > filelen) return;
286 
288  folder = GETWORD(cffile_FolderIndex);
289  attribs = GETWORD(cffile_Attribs);
290 
291  switch (folder) {
293  folder_type = "continued from prev and to next cabinet"; break;
295  folder_type = "continued from prev cabinet"; break;
297  folder_type = "continued to next cabinet"; break;
298  default:
299  folder_type = folder >= num_folders
300  ? "INVALID FOLDER INDEX"
301  : "normal folder";
302  break;
303  }
304 
305  printf("- file %-5d @%-12"LD"%s\n", i, file_offset,
306  (file_offset > min_data_offset ? " [INVALID FILE OFFSET]" : ""));
307  printf(" - name = %s%s\n", read_name(),
308  (attribs & MSCAB_ATTRIB_UTF_NAME) ? " (UTF-8)" : "");
309  printf(" - folder = 0x%04x [%s]\n", folder, folder_type);
310  printf(" - length = %u bytes\n", GETLONG(cffile_UncompressedSize));
311  printf(" - offset = %u bytes\n", GETLONG(cffile_FolderOffset));
312  printf(" - date = %02d/%02d/%4d %02d:%02d:%02d\n",
313  (GETWORD(cffile_Date)) & 0x1f,
314  (GETWORD(cffile_Date) >> 5) & 0xf,
315  (GETWORD(cffile_Date) >> 9) + 1980,
316  (GETWORD(cffile_Time) >> 11),
317  (GETWORD(cffile_Time) >> 5) & 0x3f,
318  (GETWORD(cffile_Time) << 1) & 0x3e);
319  printf(" - attrs = 0x%02x %s%s%s%s%s%s\n",
320  attribs,
321  (attribs & MSCAB_ATTRIB_RDONLY) ? "RDONLY " : "",
322  (attribs & MSCAB_ATTRIB_HIDDEN) ? "HIDDEN " : "",
323  (attribs & MSCAB_ATTRIB_SYSTEM) ? "SYSTEM " : "",
324  (attribs & MSCAB_ATTRIB_ARCH) ? "ARCH " : "",
325  (attribs & MSCAB_ATTRIB_EXEC) ? "EXEC " : "",
326  (attribs & MSCAB_ATTRIB_UTF_NAME) ? "UTF-8" : "");
327  }
328 }
lzma_index ** i
Definition: index.h:629
#define cffile_Attribs
Definition: cab.h:40
#define cffoldCOMPTYPE_MSZIP
Definition: cab.h:50
#define cffold_NumBlocks
Definition: cab.h:32
#define cffile_Time
Definition: cab.h:39
#define cffold_SIZEOF
Definition: cab.h:34
#define cffile_SIZEOF
Definition: cab.h:41
#define cffileCONTINUED_FROM_PREV
Definition: cab.h:56
#define cfheadext_HeaderReserved
Definition: cab.h:27
#define cfheadRESERVE_PRESENT
Definition: cab.h:55
#define cfhead_FileOffset
Definition: cab.h:18
#define cffile_FolderOffset
Definition: cab.h:36
#define cffile_FolderIndex
Definition: cab.h:37
#define cfheadext_DataReserved
Definition: cab.h:29
#define cffoldCOMPTYPE_LZX
Definition: cab.h:52
#define cfhead_MajorVersion
Definition: cab.h:20
#define cffoldCOMPTYPE_MASK
Definition: cab.h:48
#define cffileCONTINUED_PREV_AND_NEXT
Definition: cab.h:58
#define cfdata_UncompressedSize
Definition: cab.h:44
#define cffoldCOMPTYPE_QUANTUM
Definition: cab.h:51
#define cffile_Date
Definition: cab.h:38
#define cfheadNEXT_CABINET
Definition: cab.h:54
#define cffileCONTINUED_TO_NEXT
Definition: cab.h:57
#define cffile_UncompressedSize
Definition: cab.h:35
#define cfhead_CabinetIndex
Definition: cab.h:25
#define cfhead_SetID
Definition: cab.h:24
#define cfhead_NumFiles
Definition: cab.h:22
#define cfhead_SIZEOF
Definition: cab.h:26
#define cfhead_MinorVersion
Definition: cab.h:19
#define cfhead_NumFolders
Definition: cab.h:21
#define cfhead_CabinetSize
Definition: cab.h:17
#define cfdata_CheckSum
Definition: cab.h:42
#define cfheadext_FolderReserved
Definition: cab.h:28
#define cfheadext_SIZEOF
Definition: cab.h:30
#define cffoldCOMPTYPE_NONE
Definition: cab.h:49
#define cffold_DataOffset
Definition: cab.h:31
#define cffold_CompType
Definition: cab.h:33
#define cfhead_Flags
Definition: cab.h:23
#define cfdata_SIZEOF
Definition: cab.h:45
#define cfheadPREV_CABINET
Definition: cab.h:53
#define cfdata_CompressedSize
Definition: cab.h:43
#define MSCAB_ATTRIB_HIDDEN
Definition: mspack.h:921
#define MSCAB_ATTRIB_EXEC
Definition: mspack.h:927
#define MSCAB_ATTRIB_UTF_NAME
Definition: mspack.h:929
#define MSCAB_ATTRIB_ARCH
Definition: mspack.h:925
#define MSCAB_ATTRIB_RDONLY
Definition: mspack.h:919
#define MSCAB_ATTRIB_SYSTEM
Definition: mspack.h:923
#define GETWORD(n)
Definition: cabinfo.c:174
char * read_name()
Definition: cabinfo.c:332
#define MIN(a, b)
Definition: cabinfo.c:78
#define GETBYTE(n)
Definition: cabinfo.c:175
#define GETLONG(n)
Definition: cabinfo.c:173
#define READ(buf, len)
Definition: cabinfo.c:80
#define SEEK(offset)
Definition: cabinfo.c:82
#define GETOFFSET
Definition: cabinfo.c:79
#define FILELEN
Definition: cabinfo.c:45
#define SKIP(offset)
Definition: cabinfo.c:81
FILELEN filelen
Definition: cabinfo.c:54
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
voidpf void * buf
Definition: ioapi.h:138
#define LD
Definition: macros.h:27
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123

References cfdata_CheckSum, cfdata_CompressedSize, cfdata_SIZEOF, cfdata_UncompressedSize, cffile_Attribs, cffile_Date, cffile_FolderIndex, cffile_FolderOffset, cffile_SIZEOF, cffile_Time, cffile_UncompressedSize, cffileCONTINUED_FROM_PREV, cffileCONTINUED_PREV_AND_NEXT, cffileCONTINUED_TO_NEXT, cffold_CompType, cffold_DataOffset, cffold_NumBlocks, cffold_SIZEOF, cffoldCOMPTYPE_LZX, cffoldCOMPTYPE_MASK, cffoldCOMPTYPE_MSZIP, cffoldCOMPTYPE_NONE, cffoldCOMPTYPE_QUANTUM, cfhead_CabinetIndex, cfhead_CabinetSize, cfhead_FileOffset, cfhead_Flags, cfhead_MajorVersion, cfhead_MinorVersion, cfhead_NumFiles, cfhead_NumFolders, cfhead_SetID, cfhead_SIZEOF, cfheadext_DataReserved, cfheadext_FolderReserved, cfheadext_HeaderReserved, cfheadext_SIZEOF, cfheadNEXT_CABINET, cfheadPREV_CABINET, cfheadRESERVE_PRESENT, FILELEN, filelen, flags, GETBYTE, GETLONG, GETOFFSET, GETWORD, i, LD, MIN, MSCAB_ATTRIB_ARCH, MSCAB_ATTRIB_EXEC, MSCAB_ATTRIB_HIDDEN, MSCAB_ATTRIB_RDONLY, MSCAB_ATTRIB_SYSTEM, MSCAB_ATTRIB_UTF_NAME, printf(), READ, read_name(), SEEK, and SKIP.

Referenced by search().

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 56 of file cabinfo.c.

56  {
57  int i;
58 
59  printf("Cabinet information dumper by Stuart Caie <kyzer@cabextract.org.uk>\n");
60 
61  if (argc <= 1) {
62  printf("Usage: %s <file.cab>\n", argv[0]);
63  return 1;
64  }
65 
66  for (i = 1; i < argc; i++) {
67  if ((fh = fopen((filename = argv[i]), "rb"))) {
68  search();
69  fclose(fh);
70  }
71  else {
72  perror(filename);
73  }
74  }
75  return 0;
76 }
FILE * fh
Definition: cabinfo.c:52
void search()
Definition: cabinfo.c:91
const char * filename
Definition: ioapi.h:137
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40

References argv, fh, i, printf(), and search().

◆ myread()

int myread ( void *  buf,
size_t  length 
)

Definition at line 83 of file cabinfo.c.

83  {
84  length = MIN(length, (int)(filelen - GETOFFSET));
85  return fread(buf, 1, length, fh) != length;
86 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133

References fh, filelen, GETOFFSET, length, and MIN.

Referenced by read_name().

◆ read_name()

char * read_name ( )

Definition at line 332 of file cabinfo.c.

332  {
333  FILELEN name_start = GETOFFSET;
334  int i;
335  if (myread(&namebuf, CAB_NAMEMAX)) return "READ FAILED";
336  for (i = 0; i <= 256; i++) {
337  if (!namebuf[i]) {
338  FSEEK(fh, name_start + i + 1, SEEK_SET);
339  return namebuf;
340  }
341  }
342  printf("INVALID: name length > 256 for at offset %"LD"\n", name_start);
343  namebuf[256] = 0;
344  FSEEK(fh, name_start + 257, SEEK_SET);
345  return namebuf;
346 }
#define CAB_NAMEMAX
Definition: cabinfo.c:330
char namebuf[CAB_NAMEMAX]
Definition: cabinfo.c:331
#define FSEEK
Definition: cabinfo.c:43
int myread(void *buf, size_t length)
Definition: cabinfo.c:83
#define SEEK_SET
Definition: zip.c:88

References CAB_NAMEMAX, fh, FILELEN, FSEEK, GETOFFSET, i, LD, myread(), namebuf, printf(), and SEEK_SET.

Referenced by copy_sym_name_with_namespace(), and getinfo().

◆ search()

void search ( )

Definition at line 91 of file cabinfo.c.

91  {
92  unsigned char *pstart = &search_buf[0], *pend, *p;
93  FILELEN offset, caboff, length;
94  unsigned long cablen32 = 0, foffset32 = 0;
95  int state = 0;
96 
97  if (FSEEK(fh, 0, SEEK_END) != 0) {
98  perror(filename);
99  return;
100  }
101  filelen = FTELL(fh);
102  if (FSEEK(fh, 0, SEEK_SET) != 0) {
103  perror(filename);
104  return;
105  }
106 
107  printf("Examining file \"%s\" (%"LD" bytes)...\n", filename, filelen);
108 
109  for (offset = 0; offset < filelen; offset += length) {
110  /* search length is either the full length of the search buffer,
111  * or the amount of data remaining to the end of the file,
112  * whichever is less. */
113  length = filelen - offset;
115 
116  /* fill the search buffer with data from disk */
117  SEEK(offset);
118  READ(&search_buf[0], length);
119 
120  /* read through the entire buffer. */
121  p = pstart;
122  pend = &search_buf[length];
123  while (p < pend) {
124  switch (state) {
125  /* starting state */
126  case 0:
127  /* we spend most of our time in this while loop, looking for
128  * a leading 'M' of the 'MSCF' signature */
129  while (*p++ != 0x4D && p < pend);
130  if (p < pend) state = 1; /* if we found the 'M', advance state */
131  break;
132 
133  /* verify that the next 3 bytes are 'S', 'C' and 'F' */
134  case 1: state = (*p++ == 0x53) ? 2 : 0; break;
135  case 2: state = (*p++ == 0x43) ? 3 : 0; break;
136  case 3: state = (*p++ == 0x46) ? 4 : 0; break;
137 
138  /* we don't care about bytes 4-7 */
139  /* bytes 8-11 are the overall length of the cabinet */
140  case 8: cablen32 = *p++; state++; break;
141  case 9: cablen32 |= *p++ << 8; state++; break;
142  case 10: cablen32 |= *p++ << 16; state++; break;
143  case 11: cablen32 |= *p++ << 24; state++; break;
144 
145  /* we don't care about bytes 12-15 */
146  /* bytes 16-19 are the offset within the cabinet of the filedata */
147  case 16: foffset32 = *p++; state++; break;
148  case 17: foffset32 |= *p++ << 8; state++; break;
149  case 18: foffset32 |= *p++ << 16; state++; break;
150  case 19: foffset32 |= *p++ << 24;
151  /* now we have recieved 20 bytes of potential cab header. */
152  /* work out the offset in the file of this potential cabinet */
153  caboff = offset + (p-pstart) - 20;
154  /* check that the files offset is less than the alleged length
155  * of the cabinet */
156  if (foffset32 < cablen32) {
157  /* found a potential result - try loading it */
158  getinfo(caboff);
159  offset = caboff + (FILELEN) cablen32;
160  length = 0;
161  p = pend;
162  }
163  state = 0;
164  break;
165 
166  default:
167  p++, state++; break;
168  } /* switch state */
169  } /* while p < pend */
170  } /* while offset < filelen */
171 }
#define SEARCH_SIZE
Definition: cabinfo.c:88
#define FTELL
Definition: cabinfo.c:44
void getinfo(FILELEN base_offset)
Definition: cabinfo.c:177
unsigned char search_buf[SEARCH_SIZE]
Definition: cabinfo.c:89
voidpf uLong offset
Definition: ioapi.h:144
void * p
Definition: libc.cpp:67
Definition: dis.h:43
#define SEEK_END
Definition: zip.c:84

References fh, FILELEN, filelen, FSEEK, FTELL, getinfo(), LD, length, p, printf(), READ, search_buf, SEARCH_SIZE, SEEK, SEEK_END, and SEEK_SET.

Referenced by _cb_hit(), do_analysis_search(), do_esil_search(), do_string_search(), do_syscall_search(), main(), rz_cmd_search(), and rz_core_search_rop().

Variable Documentation

◆ fh

◆ filelen

FILELEN filelen

Definition at line 54 of file cabinfo.c.

Referenced by cabd_extract(), cabd_search(), create_output_name(), getinfo(), myread(), and search().

◆ filename

char* filename

Definition at line 53 of file cabinfo.c.

◆ namebuf

char namebuf[CAB_NAMEMAX]

Definition at line 331 of file cabinfo.c.

Referenced by read_name(), and uv__pthread_setname_np().

◆ search_buf

unsigned char search_buf[SEARCH_SIZE]

Definition at line 89 of file cabinfo.c.

Referenced by cabd_search(), and search().