static PyObject* py_magic_check(PyObject* self, PyObject* args) { PyObject *pycookie; magic_t cookie; char* filename = NULL; int result; if(!(PyArg_ParseTuple(args, "O|s", &pycookie, &filename))) return NULL; cookie = PyCObject_AsVoidPtr(pycookie); result = magic_check(cookie, filename); return PyInt_FromLong(result); }
int main (int argc, char *args[]) { int i, n, r, c, ch; FILE *inf; marklistptr library = NULL, list = NULL, step = NULL; marklistptr symbol_list = NULL; marktype d, d2; Pixel **bitmap, **recon, **bitmapcopy; char *splitfilename = NULL; int cols, rows, count, librarysize, lossy = 1; int quick = 0; int ticencode = 0, ticdecode = 0, external = 0; char *libraryname = NULL, *infile = NULL; char *s1 = NULL, *s2 = NULL; char bufferin[BUFSIZ], bufferout[BUFSIZ]; if (argc < 2) usage (); while ((ch = getopt (argc, args, "edlLQhvXR:")) != -1) switch (ch) { case 'e': ticencode = 1; break; case 'd': ticdecode = 1; break; case 'l': lossy = 1; break; case 'L': lossy = 0; break; case 'Q': quick = 1; break; case 'v': V = 1; break; case 'X': external = 1; break; case 'R': splitfilename = optarg; break; case 'h': case '?': usage (); } for (i = 1; i < argc; i++) if (args[i][0] != '-') if (strcmp (args[i - 1], "-R")) { /* ignore arg following -R, ie. -R <filename> */ if (!s1) s1 = args[i]; else if (!s2) s2 = args[i]; else error_msg (args[0], "too many filenames", ""); } if (ticencode == ticdecode) error_msg (args[0], "please specify either encode XOR decode", ""); if (ticencode) { /***************** ENCODING STAGE *****************/ long PrevBits = 0; long BITS_header = 0, BITS_symbols = 0, BITS_offsets = 0, BITS_residue = 0, BITS_footer = 0, BITS_library = 0; libraryname = s1; if (!libraryname) error_msg (args[0], "please specify a library file", ""); infile = s2; if (!infile) error_msg (args[0], "please specify a file name", ""); inf = fopen (infile, "rb"); if (inf == NULL) error_msg (args[0], "Trouble opening file:", infile); setbuf (inf, bufferin); count = librarysize = read_library (libraryname, &library); if (V) fprintf (stderr, "%s: processing...\n", args[0]); if (pbm_isapbmfile (inf)) { if (V) fprintf (stderr, "reading file %s...\n", infile); bitmap = pbm_readfile (inf, &cols, &rows); fclose (inf); bitmapcopy = pbm_copy (bitmap, cols, rows); if (V) fprintf (stderr, "extracting..."); ExtractAllMarks (bitmap, &list, cols, rows); if (V) fprintf (stderr, "(%d marks)\n", marklist_length (list)); /* sort into reading order */ if (V) fprintf (stderr, "sorting...\n"); list = sortmarks (list); pbm_freearray (&bitmap, rows); /* clear old version */ bitmap = bitmapcopy; /* point to the copy */ recon = pbm_allocarray (cols, rows); if (V) fprintf (stderr, "matching..."); match_sequence (list, library, &symbol_list, recon, quick); PrevBits = 0; setbuf (stdout, bufferout); /* start output */ magic_write (stdout, MAGIC_TIC); InitArithEncoding (); EncodeGammaDist (1); /* version 1 of the program */ EncodeGammaDist (lossy); /* lossy=1 = no residue */ EncodeGammaDist (external); /* 1== external file */ count = marklist_length (symbol_list); if (V) fprintf (stderr, "encoding cols, rows, and number of symbols=%d\n", count); EncodeGammaDist (cols); EncodeGammaDist (rows); EncodeGammaDist (count); EncodeGammaDist (librarysize); BITS_header = CountOfBitsOut - PrevBits; PrevBits = CountOfBitsOut; /* output the library sequence */ if (external == 0) { if (V) fprintf (stderr, "encoding library\n"); bl_clearmodel (); bl_writetemplate (library_template); for (step = library; step; step = step->next) bl_compress_mark (step->data); bl_freemodel (); BITS_library = CountOfBitsOut - PrevBits; PrevBits = CountOfBitsOut; } /* output the symbol sequence */ if (V) fprintf (stderr, "encoding symbol sequence\n"); InitPPM (); EncodeSymbols (symbol_list, count); BITS_symbols = CountOfBitsOut - PrevBits; PrevBits = CountOfBitsOut; /* output the offset sequence */ if (V) fprintf (stderr, "encoding offset sequence\n"); EncodeOffsets (symbol_list, count); BITS_offsets = CountOfBitsOut - PrevBits; PrevBits = CountOfBitsOut; EncodeChecksum (); /* code lossy checksum */ /* calculate the residue...and compress it---if need be! */ if (!lossy) { if (V) fprintf (stderr, "encoding residue...\n"); d.bitmap = bitmap; d.h = rows; d.w = cols; d2.bitmap = recon; d2.h = rows; d2.w = cols; if (splitfilename) { FILE *temp; CloseDownArithEncoding (); fclose (stdout); /* no residue result */ BITS_footer = CountOfBitsOut - PrevBits; temp = fopen (splitfilename, "wb"); if (temp == NULL) error_msg (args[0], "Trouble creating file:", splitfilename); arith_out = temp; InitArithEncoding (); bl_clair_compress (d, d2); CloseDownArithEncoding (); BITS_residue = CountOfBitsOut; fclose (temp); } else { bl_clair_compress (d, d2); BITS_residue = CountOfBitsOut - PrevBits; PrevBits = CountOfBitsOut; EncodeChecksum (); /* code lossless checksum */ CloseDownArithEncoding (); BITS_footer = CountOfBitsOut - PrevBits; } } else { if (V) fprintf (stderr, "not encoding residue..lossy mode\n"); CloseDownArithEncoding (); BITS_footer = CountOfBitsOut - PrevBits; } /* because we edit the values above */ CountOfBitsOut = BITS_header + BITS_library + BITS_symbols + BITS_offsets + BITS_residue + BITS_footer; fprintf (stderr, "bits: header=%ld, library=%ld, " "symbols=%ld, offsets=%ld, residue=%ld, footer=%ld\n", BITS_header, BITS_library, BITS_symbols, BITS_offsets, BITS_residue, BITS_footer); fprintf (stderr, "total bits: %ld, ", CountOfBitsOut); fprintf (stderr, "Lossy CR: %4.2f", (cols * rows) / (float) (CountOfBitsOut - BITS_residue)); if (external) fprintf (stderr, " (excluding external lib)"); fprintf (stderr, ", Lossless CR: %4.2f\n", (!lossy) * (cols * rows) / (float) (CountOfBitsOut)); } else error_msg (args[0], "unknown format of bitmap--expecting PBM.", ""); } else { /***************** DECODING STAGE *****************/ int lastx, lasty; librarysize = 0; if (external) { libraryname = s1; infile = s2; count = librarysize = read_library (libraryname, &library); } else { infile = s1; if (infile && s2) error_msg (args[0], "too many filenames", ""); } if (!freopen (infile, "rb", stdin)) error_msg (args[0], "Trouble opening file:", infile); if (V) fprintf (stderr, "decompressing...\n"); setbuf (stdin, bufferin); magic_check (stdin, MAGIC_TIC); InitArithDecoding (); { int version = DecodeGammaDist (); if (version != 1) error_msg (args[0], "Need later version of decompressor.", ""); } { int templossy = DecodeGammaDist (); if (!lossy) lossy = templossy; /* can only choose if encoded file is lossless */ if (V) { if (lossy) fprintf (stderr, "lossy mode\n"); else fprintf (stderr, "lossless mode\n"); } } if (DecodeGammaDist ()) { /* if compressed file doesn't contain library */ if (!external) error_msg (args[0], "compressed file doesn't contain library, specify externally", ""); external = 1; } else { /* if compressed file contains library */ if (external) fprintf (stderr, "ignoring external library file\n"); external = 0; } cols = DecodeGammaDist (); rows = DecodeGammaDist (); count = DecodeGammaDist (); i = DecodeGammaDist (); /* librarysize */ if (external) { if (i > librarysize) error_msg (args[0], "external library file is too small!", ""); else if (i < librarysize) fprintf (stderr, "%s: warning, expecting a different (smaller) library.\n", args[0]); } librarysize = i; if (V) fprintf (stderr, "cols %d, rows %d, num syms %d, library size %d\n", cols, rows, count, librarysize); /* decode library */ if (external == 0) { if (V) fprintf (stderr, "reading library\n"); bl_clearmodel (); bl_readtemplate (); for (n = 0; n < librarysize; n++) { bl_decompress_mark (&d); d.symnum = n; if (library == NULL) step = marklist_add (&library, d); else step = marklist_add (&step, d); } bl_freemodel (); if (V) fprintf (stderr, "read %d marks from library\n", marklist_length (library)); } recon = pbm_allocarray (cols, rows); /* decode symbols */ InitPPM (); if (V) fprintf (stderr, "decompressing %d symbols\n", count); symbol_list = DecodeSymbols (count); /* decode offsets */ if (V) fprintf (stderr, "reading offsets...\n"); DecodeOffsets (symbol_list, count); lastx = lasty = 0; for (step = symbol_list; step; step = step->next) { lastx = lastx + step->data.xoffset; lasty = lasty + step->data.yoffset; marklist_getat (library, step->data.symnum, &d2); for (r = 0; r < d2.h; r++) for (c = 0; c < d2.w; c++) if (pbm_getpixel (d2.bitmap, c, r)) pbm_putpixel_trunc (recon, lastx + c, lasty + r, 1, cols, rows); /* we don't care, already warned them! */ lastx += d2.w; } DecodeChecksum (args[0]); /* decode the residue */ if (!lossy) { if (V) fprintf (stderr, "decoding residue...\n"); bitmap = pbm_allocarray (cols, rows); d.bitmap = bitmap; d.w = d2.w = cols; d.h = d2.h = rows; d2.bitmap = recon; /* NOTE: the 2nd argument is clairvoyantly compressed */ if (splitfilename) { FILE *temp; CloseDownArithDecoding (); fclose (stdin); temp = fopen (splitfilename, "rb"); if (temp == NULL) error_msg (args[0], "Trouble opening file:", splitfilename); arith_in = temp; InitArithDecoding (); bl_clair_decompress (d, d2); CloseDownArithDecoding (); fclose (temp); } else { bl_clair_decompress (d, d2); DecodeChecksum (args[0]); CloseDownArithDecoding (); } pbm_freearray (&recon, rows); recon = bitmap; /* point to the bitmap */ } else { CloseDownArithDecoding (); } if (V) fprintf (stderr, "writing pbm file...\n"); setbuf (stdout, bufferout); pbm_writefile (stdout, recon, cols, rows); pbm_freearray (&recon, rows); } /* end decoding */ exit(0); }
R_API int r_magic_check(RMagic* m, const char *x) { return magic_check (m, x); }
int main(int argc, char *argv[]) { char *out_file = NULL, *last_optarg = NULL; char *magic_file_contents = NULL, *marker = NULL, *magic = NULL; size_t mfsize = 0; int c = 0, i = 0; int filter_count = 0, magic_offset = 0, magic_size = 0, wildcard = 0, num_sigs = 0, check_magic_file = 0, fast_filter = 0; int update = 0, ignore_short_sigs = 1, use_default_filters = 1; int retval = EXIT_FAILURE; struct magic_signature *signatures[MAX_SIGNATURES]; struct magic_filter *filters[MAX_FILTERS]; struct binconf config = { 0 }; int long_opt_index = 0; char *short_options = "b:l:m:o:f:y:x:i:aAcCdkstvquh"; struct option long_options[] = { { "align", required_argument, NULL, 'b' }, { "length", required_argument, NULL, 'l' }, { "magic", required_argument, NULL, 'm' }, { "offset", required_argument, NULL, 'o' }, { "file", required_argument, NULL, 'f' }, { "search", required_argument, NULL, 'y' }, { "exclude", required_argument, NULL, 'x' }, { "include", required_argument, NULL, 'i' }, { "all", no_argument, NULL, 'a' }, { "opcodes", no_argument, NULL, 'A' }, { "validate", no_argument, NULL, 'c' }, { "cast", no_argument, NULL, 'C' }, { "defaults", no_argument, NULL, 'd' }, { "keep-going", no_argument, NULL, 'k' }, { "smart", no_argument, NULL, 's' }, { "fast", no_argument, NULL, 't' }, { "verbose", no_argument, NULL, 'v' }, { "quiet", no_argument, NULL, 'q' }, { "update", no_argument, NULL, 'u' }, { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; /* Need at least one argument: the target file */ if(argc == 1) { usage(argv[0]); goto end; } /* Initialize global variables */ memset((void *) &globals,0,sizeof(globals)); /* Initialize default configuration settings */ config.flags = MAGIC_NONE; config.align = DEFAULT_BYTE_ALIGN; config.smart = 1; while((c = getopt_long(argc, argv, short_options, long_options, &long_opt_index)) != -1) { switch(c) { case 'a': ignore_short_sigs = 0; break; case 'b': config.align = str2int(optarg); break; case 'c': check_magic_file = 1; break; case 'C': config.magic = strdup(MAGIC_CAST); config.flags |= MAGIC_CONTINUE; break; case 'A': config.magic = strdup(MAGIC_ARCH); ignore_short_sigs = 0; break; case 'f': out_file = strdup(optarg); break; case 'i': add_filter(filters, &filter_count, FILTER_ADD, optarg); break; case 'l': config.length = str2int(optarg); break; case 'm': config.magic = strdup(optarg); break; case 'o': config.offset = str2int(optarg); break; case 'd': use_default_filters = 0; break; case 's': config.smart = 0; break; case 't': fast_filter = 1; break; case 'k': config.flags |= MAGIC_CONTINUE; break; case 'y': fast_filter = 1; use_default_filters = 0; add_filter(filters, &filter_count, FILTER_INCLUDE, optarg); break; case 'x': add_filter(filters, &filter_count, FILTER_EXCLUDE, optarg); break; case 'q': globals.quiet = 1; break; case 'u': update = 1; break; case 'v': config.verbose = 1; break; default: usage(argv[0]); goto end; } /* Keep a copy of the last optarg so we can distinguish between option arguments and file names later on */ if(optarg) { if(last_optarg) free(last_optarg); last_optarg = strdup(optarg); } } /* Update magic files from SVN repository */ if(update) { printf("Updating magic signatures..."); if(update_magic_file(BINWALK_UPDATE_URL, MAGIC) && update_magic_file(BINCAST_UPDATE_URL, MAGIC_CAST) && update_magic_file(BINARCH_UPDATE_URL, MAGIC_ARCH)) { printf("finished.\n"); retval = EXIT_SUCCESS; } else { printf("failed.\n"); } goto end; } /* Unless otherwise specified, apply default filters */ if(use_default_filters) { add_filter(filters, &filter_count, FILTER_ADD, GZIP_FILTER); add_filter(filters, &filter_count, FILTER_ADD, LZMA_FILTER); add_filter(filters, &filter_count, FILTER_ADD, JFFS_FILTER); add_filter(filters, &filter_count, FILTER_EXCLUDE, INVALID_FILTER); } /* Use the default magic file if none was specified on the command line */ if(config.magic == NULL) { config.magic = strdup(MAGIC); } /* Initialize libmagic */ config.cookie = magic_open(config.flags); if(!config.cookie) { fprintf(stderr,"ERROR: Failed to initialize libmagic: %s\n", magic_error(config.cookie)); goto end; } /* Validate the magic file */ if(check_magic_file) { if(magic_check(config.cookie, config.magic) != 0) { fprintf(stderr, "ERROR: Invalid magic file '%s': %s\n", config.magic, magic_error(config.cookie)); } else { retval = EXIT_SUCCESS; } goto end; } /* If an output file was specified, open it */ if(out_file != NULL) { globals.fsout = fopen(out_file,"w"); if(!globals.fsout) { perror("ERROR: Failed to open output file for writing"); goto end; } } /* Load the magic signatures file */ if(magic_load(config.cookie, config.magic) == -1) { fprintf(stderr,"ERROR: Failed to load magic file '%s': %s\n", config.magic, magic_error(config.cookie)); goto end; } if(config.smart) { /* Load magic signatures into the signatures struct array. */ magic_file_contents = (char *) file_read((char *) config.magic, &mfsize); marker = magic_file_contents; for(i=0; i<mfsize && num_sigs < MAX_SIGNATURES; i++) { /* The first line for each magic entry will start with a decimal offset value. This is the line * that contains the actual signature, and is the one we want to parse. The rest are comments, * whitespace or subsequent signture parsing data that we let libmagic handle later on. */ if(marker[0] >= '0' && marker[0] <= '9') { /* Parse out the magic value, file offset and size for this entry */ magic = parse_magic(marker, &magic_offset, &magic_size, &wildcard, filters, filter_count, ignore_short_sigs, fast_filter); if(magic && magic_size > 0) { signatures[num_sigs] = malloc(sizeof(struct magic_signature)); signatures[num_sigs]->size = magic_size; signatures[num_sigs]->offset = magic_offset; signatures[num_sigs]->wildcard = wildcard; signatures[num_sigs]->signature = malloc(magic_size); memcpy(signatures[num_sigs]->signature, magic, magic_size); num_sigs++; } if(magic) free(magic); } /* Find the next new line. Break if not found, skip to the next character if one is found. */ marker = strstr(marker, "\n"); if(!marker) break; marker++; } } else { num_sigs = 1; } /* Process all the files specified on the command line */ for(i=argc-1; i>0; i--) { /* If we've gotten to the arguments, we're done */ if((argv[i][0] == '-') || ((last_optarg != NULL) && (strcmp(argv[i], last_optarg) == 0)) ) { break; } retval = process_file(argv[i], &config, signatures, num_sigs, filters, filter_count); } end: if(config.magic) free(config.magic); if(magic_file_contents) munmap((void *) magic_file_contents, mfsize); if(globals.fsout != NULL) fclose(globals.fsout); if(config.cookie) magic_close(config.cookie); return retval; }