Kjetil's Information Center: A Blog About My Projects

Binary Dumping Tool

Here is a homemade tool that I use when dealing with binary files. The tool will convert binary files to its binary textual representation (like 0011010000110010) and back. It can also convert to hexadecimal representation and back.

The tool is typically used for analysis (look for patterns during cryptography, steganography, etc.) or to do transformations. By transformations I mean converting to e.g. hex, change the data with some other tool and then covert back to binary.

I find the source code to be too short to be considered an "application" (with a licence), so I will just post the code directly into the public domain:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

typedef enum {
  CONV_NONE,
  CONV_TO_HEX,
  CONV_FROM_HEX,
  CONV_TO_BIN,
  CONV_FROM_BIN,
} conv_t;

static void display_help(void)
{
  fprintf(stderr, "\nOptions:\n"
     "  -h        Display this help and exit.\n"
     "  -s        Enable strict mode:\n"
     "              Disables formated output when converting 'to' or\n"
     "              warns about unknown characters when converting 'from'.\n"
     "  -o FILE   Write output to FILE instead of standard out.\n"
     "  -b        Convert to binary representation.\n"
     "  -B        Convert from binary representation.\n"
     "  -x        Convert to hex representation.\n"
     "  -X        Convert from hex representation.\n\n");
}

static int power_of_two(int n)
{
  if (n == 0)
    return 1;
  else
    return 2 * power_of_two(n - 1);
}

static void bin_output(FILE *out, int c)
{
  int i;
  for (i = 7; i >= 0; i--) {
    if (c - power_of_two(i) >= 0) {
      fprintf(out, "1");
      c -= power_of_two(i);
    } else
      fprintf(out, "0");
  }
}

static int bin_scan(FILE *in, int strict)
{
  int c, value, n;

  value = 0; 
  n = 7;
  while ((c = fgetc(in)) != EOF) {
    if (c == '0') {
      if (n <= 0)
        return value;
      n--;

    } else if (c == '1') {
      if (n <= 0)
        return value + power_of_two(n);
      else
        value += power_of_two(n);
      n--;

    } else {
      if (strict) {
        fprintf(stderr, "%s: not a 1 or 0 in conversion: 0x%02x\n",
          __FILE__, c);
        return -2;
      }
    }
  }

  return EOF;
}

static int hex_value(int c)
{
  if (c >= 0x30 && c <= 0x39) /* '0' - '9' */
    return c - 0x30;
  else if (c >= 0x41 && c <= 0x46) /* 'A' - 'F' */
    return (c - 0x41) + 10;
  else if (c >= 0x61 && c <= 0x66) /* 'a' - 'f' */
    return (c - 0x61) + 10;
  else
    return -1;
}

static int hex_scan(FILE *in, int strict)
{
  int c, high = -1;

  while ((c = fgetc(in)) != EOF) {
    if (hex_value(c) >= 0) {
      if (high == -1)
        high = c;
      else
        return hex_value(high) * 16 + hex_value(c);
    } else {
      if (strict) {
        fprintf(stderr, "%s: not a hex character in conversion: 0x%02x\n",
          __FILE__, c);
        return -2;
      }
    }
  }

  return EOF;
}

static void convert(conv_t conv, int strict, FILE *in, FILE *out)
{
  int c, space = 0;

  switch (conv) {
  case CONV_TO_BIN:
    while ((c = fgetc(in)) != EOF) {
      bin_output(out, c);
      if (! strict) {
        if (space % 8 == 7)
          fprintf(out, "\n");
        else if (space % 1 == 0)
          fprintf(out, " ");
      }
      space++;
    }
    if (! strict)
      fprintf(out, "\n");
    break;

  case CONV_FROM_BIN:
    while ((c = bin_scan(in, strict)) != EOF) {
      if (c >= 0)
        fprintf(out, "%c", c);
    }
    break;

  case CONV_TO_HEX:
    while ((c = fgetc(in)) != EOF) {
      fprintf(out, "%02x", c);
      if (! strict) {
        if (space % 24 == 23)
          fprintf(out, "\n");
        else if (space % 4 == 3)
          fprintf(out, "  ");
        else if (space % 1 == 0)
          fprintf(out, " ");
      }
      space++;
    }
    if (! strict)
      fprintf(out, "\n");
    break;

  case CONV_FROM_HEX:
    while ((c = hex_scan(in, strict)) != EOF) {
      if (c >= 0)
        fprintf(out, "%c", c);
    }
    break;

  default:
    break;
  }
}

int main(int argc, char *argv[])
{
  int c, i;
  FILE *in = NULL, *out = NULL;
  char *outfile = NULL;
  int strict = 0;
  conv_t conv = CONV_NONE;

  while ((c = getopt(argc, argv, "hso:bBxX")) != -1) {
    switch (c) {
    case 'h':
      display_help();
      exit(EXIT_SUCCESS);

    case 's':
      strict = 1;
      break;

    case 'o':
      outfile = optarg;
      break;

    case 'b':
    case 'B':
    case 'x':
    case 'X':
      if (conv != CONV_NONE) {
        fprintf(stderr,
          "%s: only one of the options b, B, x or X can be set.\n", __FILE__);
        display_help();
        exit(EXIT_FAILURE);
      } else {
        if (c == 'b')
          conv = CONV_TO_BIN;
        else if (c == 'B')
          conv = CONV_FROM_BIN;
        else if (c == 'x')
          conv = CONV_TO_HEX;
        else if (c == 'X')
          conv = CONV_FROM_HEX;
      }
      break;

    case '?':
    default:
      display_help();
      exit(EXIT_FAILURE);
    }
  }

  if (conv == CONV_NONE) {
    fprintf(stderr,
      "%s: one of the options b, B, x or X must be set.\n", __FILE__);
    display_help();
    exit(EXIT_FAILURE);
  }

  if (outfile == NULL)
    out = stdout; /* Default to stdout if no output is specified. */
  else {
    out = fopen(outfile, "w");
    if (out == NULL) {
      fprintf(stderr, "%s: unable to open output file for writing: %s\n",
        __FILE__, strerror(errno));
      exit(EXIT_FAILURE);
    }
  }

  if (argc == optind) /* No input files specified, use stdin. */
    convert(conv, strict, stdin, out);
  else {
    for (i = optind; i < argc; i++) {
      in = fopen(argv[i], "r");
      if (in == NULL) {
        fprintf(stderr, "%s: unable to open input file for reading: %s\n",
          __FILE__, strerror(errno));
        continue; /* Do not abort, try the next file. */
      }

      convert(conv, strict, in, out);
      fclose(in);
    }
  }

  fclose(out);
  return EXIT_SUCCESS;
}
          


Topic: Scripts and Code, by Kjetil @ 15/11-2008, Article Link