Skip to content

Instantly share code, notes, and snippets.

@devlavender
Last active January 27, 2022 00:38
Show Gist options
  • Save devlavender/b2d3459b3384b449f5961d496d2f7321 to your computer and use it in GitHub Desktop.
Save devlavender/b2d3459b3384b449f5961d496d2f7321 to your computer and use it in GitHub Desktop.
Quick hexdecoder to convert some irregularly formatted hex file
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <inttypes.h>
int argerror(int argc, char **argv){
char error[241];
const size_t mlen = sizeof(error) - 1;
int ret = 0;
bzero(error, mlen+1);
switch (argc) {
case 1:
strncpy(error,
"Missing both input and"
" output arguments",
mlen);
ret = -1;
break;
case 2:
strncpy(error,
"Missing output argument",
mlen);
ret = -2;
break;
case 3:
case 0:
strncpy(error,
"Mysterious runtime error,"
" it couldn't possibly"
"happen!",
mlen);
ret = -666;
break;
default:
strncpy(error,
"Unknown error",
mlen);
ret = -16;
}
fprintf(stderr, "ERROR: %s!\n", error);
fprintf(stderr,
"Usage: %s <input-file> <output-file>\n",
argv[0]);
return ret;
}
/*
* Parses input file
*
*/
int parse(FILE *input, FILE *output)
{
char *p = NULL;
char pair[3] = { 0, 0, 0 };
size_t io_size = 0;
int ret = 0;
char current;
while (
fread(
&current,
sizeof(char),
1,
input
) == 1
)
{
if (isspace(current))
continue;
if (isxdigit(current)) {
p = pair;
*p++ = current;
fread(p, sizeof(char), 1, input);
if (!isxdigit(*p)) {
fprintf(stderr,
"Invalid hex pair:"
" %s. Skipping!",
pair);
continue;
}
u_int8_t byte;
sscanf(pair, "%"SCNx8, &byte);
io_size = fwrite(&byte,
sizeof(byte),
1, output);
if (io_size < sizeof(byte)) {
int e = ferror(output);
if (e != 0)
return e;
fprintf(stderr,
"Unknown error "
"writing 0x""%X to"
"output file. The"
"output is "
"corrupted.\n",
byte);
}
ret += io_size;
}
else
if (isalnum(current) ||
isprint(current))
fprintf(stderr,
"Invalid character"
" %c. Skipping!\n",
current);
else fprintf(stderr,
"Invalid character 0x%X."
"Skipping!\n",
current);
}
return ret;
}
int main(int argc, char **argv) {
FILE *input = NULL;
FILE *output = NULL;
int exstt = 0;
void *inp_contents = NULL;
size_t read_bytes;
if (argc != 3)
return argerror(argc, argv);
if (access(argv[2], F_OK) == 0) { //output file
fprintf(stderr,
"The output file %s already exists"
"! Overwrite? (y/N)", argv[2]);
char ans;
fscanf(stdin, "%c", &ans);
if (ans != 'y' && ans != 'Y') {
fprintf(stderr,
"Aborted on user request"
"!\n");
return -32;
}
}
input = fopen(argv[1], "r");
output = fopen(argv[2], "w");
if (input == NULL || output == NULL) {
char errmsg[300];
bzero(errmsg, sizeof(errmsg));
char *ftype = NULL;
if (!output && !input)
ftype = "input and output";
else if (!output)
ftype = "output";
else
ftype = "input";
fprintf(stderr, errmsg,
"Fatal Error: could not open %s "
"file. Error code: 0x%X\n", errno);
perror("Error Details");
return errno;
// I know mixing errno codes with my own
// returns is terrible, but whatever
}
exstt = parse(input, output);
return exstt;
}
OVERVIEW
I was processing some files containing irregularly formatted
hexadecimal sequences like the ones in the file
input_example.txt. To make a more "resilient" parser than
the available options (at least those I'm aware) I did this
quick code yesterday.
QUICK AND NOT SO GOOD CODE
Keep in mind that this is a code written to be done very
quickly, so it's no good code. I have written in `vi` on a
remote server, so the identation is not ideal, the controls
are as simple as possible. It worked for my very specific
needs, though.
COMPILE
Just download hexdecode.c and then run gcc:
`
gcc -o hexdecode hexdecode.c
`
Or other parameters you'd like
# Running
If you run on command like a simple
`
./hexdecode
`
You'll see the usage instructions. Here's how to use it:
`
./hexdecode <input-file-path> <output-file-path>
`
And that's just it! It's very verbose about ignored
characters so whoever uses it can easily detect if something
goes wrong.
##########################
Here the hex chara_cters are in
pairs (expe_cte_d to b_e parse_d), separate_d by random
chara_cters:
54#68# 69,,,,73!!!!!!!!!!!!!!!!*(&$^*#$&^*!&(@^(#*&^!*(&@#*(%(*$%#(&*^!*&@#^(*!&@#^%!&@#^*!&@^#(*&!^@(*#%(!*&@#^*(!@^#*!@^(*&#!^*(@&^#(*!&@*(#
rtyrtyrtyrtyrtyrtyrtyrtyrtyrty
rtyrtyrtyrt
yrtyrtyrtyrtyrty
rtyrtyrtyrtyrtyrtyrt
I am a d d i n g some
h e x d i g i t s
here, isolate#d, to makesure they
will not b#e parse#d unless they are in
conse_cutive
pairs!
0!1#2$3%4^5&6*7(8)9
a_b_c_d_e
A_B_C_D_E
<?><?><?><?><?>**(&%&^$%$^%$*&*^&*%$%#
####################################
Now in blocks split into spa_c_e_d pairs:
20 69 73 20 61 20 74 65 73 74 20 6d 65 73 73 61
67 65 2c 20 61 20 74 65 73 74 20 6f 66 20 74 68
Now in URL format:
%65%20%73%61%6d%65%20%6b%69%6e%64%0a%6f%66%0a%66%%%
Now in a single sequenc`e:
696c6520495f414d5f5553494e472cc3a727c3a90a746865206865786465636f646520746f2070617273650a284f42533a2072616e646f6d207370656369616c206368617261637465727320696e20746865206d6964646c652061726520696e74656e64656429
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment