I'm attempting to recreate a hexdump program in C. This is what I have so far
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef unsigned char byte;
void openfile(FILE **fptr, char *fname)
{
*fptr = fopen(fname, "r");
if(fptr == NULL)
{
fprintf(stderr, "How dare you... \n");
exit(-1);
}
}
int readContents(FILE *fptr, int *filesize, byte *array)
{
return (fread(array, 1, *filesize, fptr)); // read all bytes from the file
}
int printit(FILE **fptr, int *filesize, byte *array)
{
byte sixteen[17];
readContents(*fptr, filesize, array);
int idx;
for(idx = 0; idx <= *filesize; idx++)
{
if((idx%16)==0)
{
printf("%08x ", idx);
}
if((idx%8)==0)
{
printf(" ");
}
printf("%02x ", array[idx]);
if((idx+1)%16==0)
{
printf("\n");
}
}
for(idx = 0; idx <= *filesize; idx++)
{
if((idx%16)==0)
printf("%c ", array[idx]);
}
}
int main(int argc, char *argv[])
{
char filename[30];
if(argc > 1)
{
strcpy(filename, argv[1]);
}
else
{
printf("Please enter a filename: ");
scanf(" %[^\n]s", filename);
}
FILE *ptr;
openfile(&ptr, filename);
fseek(ptr, 0, SEEK_END);
int filelen = ftell(ptr);
printf("Length of file is: %d\n", filelen);
fseek(ptr, 0, SEEK_SET);
byte *bytes = malloc(filelen);
printit(&ptr, &filelen, bytes);
printf("\n");
free(bytes);
fclose(ptr);
}
The offset placement and hexes appear successfully in the output, but I just can't seem to figure out how I should add a column on the right hand side with the plaintext of the contents of a file
This is what the output looks like without it
00000010 03 00 3e 00 01 00 00 00 70 09 00 00 00 00 00 00
00000020 40 00 00 00 00 00 00 00 98 2b 00 00 00 00 00 00
00000030 00 00 00 00 40 00 38 00 09 00 40 00 1d 00 1c 00
00000040 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00 00
00000050 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
00000060 f8 01 00 00 00 00 00 00 f8 01 00 00 00 00 00 00
00000070 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00
00000080 38 02 00 00 00 00 00 00 38 02 00 00 00 00 00 00
00000090 38 02 00 00 00 00 00 00 1c 00 00 00 00 00 00 00
000000a0 1c 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
000000b0 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00
000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000d0 38 0f 00 00 00 00 00 00 38 0f 00 00 00 00 00 00
000000e0 00 00 20 00 00 00 00 00 01 00 00 00 06 00 00 00
000000f0 50 1d 00 00 00 00 00 00 50 1d 20 00 00 00 00 00
00000100 50 1d 20 00 00 00 00 00 c0 02 00 00 00 00 00 00
00000110 e0 02 00 00 00 00 00 00 00 00 20 00 00 00 00 00
00000120 02 00 00 00 06 00 00 00 60 1d 00 00 00 00 00 00
00000130 60 1d 20 00 00 00 00 00 60 1d 20 00 00 00 00 00
00000140 f0 01 00 00 00 00 00 00 f0 01 00 00 00 00 00 00
00000150 08 00 00 00 00 00 00 00 04 00 00 00 04 00 00 00
00000160 54 02 00 00 00 00 00 00 54 02 00 00 00 00 00 00
00000170 54 02 00 00 00 00 00 00 44 00 00 00 00 00 00 00
00000180 44 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00
00000190 50 e5 74 64 04 00 00 00 f0 0d 00 00 00 00 00 00
000001a0 f0 0d 00 00 00 00 00 00 f0 0d 00 00 00 00 00 00
000001b0 3c 00 00 00 00 00 00 00 3c 00 00 00 00 00 00 00
000001c0 04 00 00 00 00 00 00 00 51 e5 74 64 06 00 00 00
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
And this is where the plaintext appears at the end
@ @ � 8 8 8 P P � ` � T T D P � < R P � d o G G ` J o + D u �
� h . e n a c o s i i i L . I C n e b u P p � � p � � � � � � � � � � � � � � � � � � � � � � 1 � � H 9 � ] H ) H � ] � � � U � � � � 5 � � H � U � � � � � � H , � � � � H � � � � � d � A � � L A � n : D . V x f F d f � X � �
� � � A p
�
� � � � � ` � � � � 6 V G . 4 8 t � � 0 X ` � P ` � 0 7 X m P � � � ` � � � K g � � � � ' C e 0 � + f z w � � � X f m o o d a n n e A _ M _ F L _ p . a . e r 5 @ t L G b L a @ l _ _ s c @ b o 5 @ @ T e b I f 2 I a r t . n . s n e l n r m f m c 8 T t � � � � � 0 B X p ` p � 0 P X ` P 0 @ x �
I also happen to be reading an ELF file, FYI
EDIT: I forgot to paste #include stdio.h
the following proposed code:
malloc()
and free()
and now, the proposed code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#define MAX_BYTES 16
#define MAX_FILENAME_LEN 30
typedef unsigned char byte;
static unsigned int idx = 0;
void printit( size_t bytesRead, byte *array)
{
// display index into file
printf("\n%08x ", idx);
for( size_t i = 0; i < bytesRead; i++ )
{
if( i == 8 )
{
printf(" ");
}
printf("%02x ", array[i]);
}
printf( "%s", " | " );
for( size_t i = 0; i< bytesRead; i++ )
{
if( isalpha( array[i] ) )
{
printf( "%c", array[i] );
}
else
{
printf( "%c", '.' );
}
}
printf( "%s", " | " );
idx += (unsigned int)bytesRead;
}
int main(int argc, char *argv[])
{
char filename[ MAX_FILENAME_LEN ];
if(argc > 1)
{
strncpy(filename, argv[1], MAX_FILENAME_LEN );
}
else
{
printf("Please enter a filename: ");
if( scanf("%29s", filename) != 1 )
{
fprintf( stderr, "scanf to get filename from user failed\n" );
exit( EXIT_FAILURE );
}
}
FILE *fp = fopen(filename, "rb");
if( ! fp )
{
perror( "fopen for input file failed");
exit( EXIT_FAILURE );
}
fseek( fp, 0, SEEK_END );
long filelen = ftell( fp );
printf("Length of file is: %ld\n", filelen);
fseek( fp, 0, SEEK_SET );
byte filedata[ 16 ];
size_t bytesRead;
while( ( bytesRead = fread( filedata, 1, sizeof filedata, fp )) > 0 )
{
//printf( "bytesRead: %zu\n", bytesRead );
printit( bytesRead, filedata );
}
fclose( fp );
}
here is a typical run of the proposed code, against the source file:
Please enter a filename: untitled2.c
Length of file is: 1533
00000000 09 23 69 6e 63 6c 75 64 65 20 3c 73 74 72 69 6e | ..include..strin |
00000010 67 2e 68 3e 0a 09 23 69 6e 63 6c 75 64 65 20 3c | g.h....include.. |
00000020 73 74 64 6c 69 62 2e 68 3e 0a 09 23 69 6e 63 6c | stdlib.h....incl |
00000030 75 64 65 20 3c 73 74 64 69 6f 2e 68 3e 0a 09 23 | ude..stdio.h.... |
00000040 69 6e 63 6c 75 64 65 20 3c 63 74 79 70 65 2e 68 | include..ctype.h |
00000050 3e 0a 0a 0a 09 23 64 65 66 69 6e 65 20 4d 41 58 | ......define.MAX |
00000060 5f 42 59 54 45 53 20 31 36 0a 09 23 64 65 66 69 | .BYTES......defi |
00000070 6e 65 20 4d 41 58 5f 46 49 4c 45 4e 41 4d 45 5f | ne.MAX.FILENAME. |
00000080 4c 45 4e 20 33 30 0a 0a 09 74 79 70 65 64 65 66 | LEN......typedef |
00000090 20 75 6e 73 69 67 6e 65 64 20 63 68 61 72 20 62 | .unsigned.char.b |
000000a0 79 74 65 3b 0a 0a 09 73 74 61 74 69 63 20 75 6e | yte....static.un |
000000b0 73 69 67 6e 65 64 20 69 6e 74 20 69 64 78 20 3d | signed.int.idx.. |
000000c0 20 30 3b 0a 0a 09 76 6f 69 64 20 70 72 69 6e 74 | ......void.print |
000000d0 69 74 28 20 73 69 7a 65 5f 74 20 62 79 74 65 73 | it..size.t.bytes |
000000e0 52 65 61 64 2c 20 62 79 74 65 20 2a 61 72 72 61 | Read..byte..arra |
000000f0 79 29 0a 09 7b 0a 09 09 2f 2f 20 64 69 73 70 6c | y..........displ |
00000100 61 79 20 69 6e 64 65 78 20 69 6e 74 6f 20 66 69 | ay.index.into.fi |
00000110 6c 65 0a 09 09 70 72 69 6e 74 66 28 22 5c 6e 25 | le...printf...n. |
00000120 30 38 78 20 22 2c 20 69 64 78 29 3b 0a 09 09 0a | ..x....idx...... |
00000130 09 09 66 6f 72 28 20 73 69 7a 65 5f 74 20 69 20 | ..for..size.t.i. |
00000140 3d 20 30 3b 20 69 20 3c 20 62 79 74 65 73 52 65 | .....i...bytesRe |
00000150 61 64 3b 20 69 2b 2b 20 20 29 0a 09 09 7b 0a 09 | ad..i........... |
00000160 09 09 69 66 28 20 69 20 3d 3d 20 38 20 29 0a 09 | ..if..i......... |
00000170 09 09 7b 0a 09 09 09 09 70 72 69 6e 74 66 28 22 | ........printf.. |
00000180 20 22 29 3b 0a 09 09 09 7d 0a 0a 09 09 09 70 72 | ..............pr |
00000190 69 6e 74 66 28 22 25 30 32 78 20 22 2c 20 61 72 | intf.....x....ar |
000001a0 72 61 79 5b 69 5d 29 3b 0a 09 09 7d 0a 09 09 0a | ray.i........... |
000001b0 09 09 70 72 69 6e 74 66 28 20 22 25 73 22 2c 20 | ..printf....s... |
000001c0 22 20 7c 20 22 20 29 3b 0a 09 09 0a 09 09 66 6f | ..............fo |
000001d0 72 28 20 73 69 7a 65 5f 74 20 69 20 3d 20 30 3b | r..size.t.i..... |
000001e0 20 69 3c 20 62 79 74 65 73 52 65 61 64 3b 20 69 | .i..bytesRead..i |
000001f0 2b 2b 20 29 0a 09 09 7b 0a 09 09 09 69 66 28 20 | ............if.. |
00000200 69 73 61 6c 70 68 61 28 20 61 72 72 61 79 5b 69 | isalpha..array.i |
00000210 5d 20 29 20 29 0a 09 09 09 7b 0a 09 09 09 09 20 | ................ |
00000220 70 72 69 6e 74 66 28 20 22 25 63 22 2c 20 61 72 | printf....c...ar |
00000230 72 61 79 5b 69 5d 20 29 3b 0a 09 09 09 7d 0a 09 | ray.i........... |
00000240 09 09 20 0a 09 09 09 65 6c 73 65 0a 09 09 09 7b | .......else..... |
00000250 0a 09 09 09 09 20 70 72 69 6e 74 66 28 20 22 25 | ......printf.... |
00000260 63 22 2c 20 27 2e 27 20 29 3b 0a 09 09 09 7d 0a | c............... |
00000270 09 09 7d 0a 09 09 70 72 69 6e 74 66 28 20 22 25 | ......printf.... |
00000280 73 22 2c 20 22 20 7c 20 22 20 29 3b 0a 09 09 0a | s............... |
00000290 09 09 69 64 78 20 2b 3d 20 28 75 6e 73 69 67 6e | ..idx.....unsign |
000002a0 65 64 20 69 6e 74 29 62 79 74 65 73 52 65 61 64 | ed.int.bytesRead |
000002b0 3b 20 20 0a 09 7d 0a 0a 0a 09 69 6e 74 20 6d 61 | ..........int.ma |
000002c0 69 6e 28 69 6e 74 20 61 72 67 63 2c 20 63 68 61 | in.int.argc..cha |
000002d0 72 20 2a 61 72 67 76 5b 5d 29 0a 09 7b 0a 09 09 | r..argv......... |
000002e0 63 68 61 72 20 66 69 6c 65 6e 61 6d 65 5b 20 4d | char.filename..M |
000002f0 41 58 5f 46 49 4c 45 4e 41 4d 45 5f 4c 45 4e 20 | AX.FILENAME.LEN. |
00000300 5d 3b 0a 0a 09 09 69 66 28 61 72 67 63 20 3e 20 | ......if.argc... |
00000310 31 29 0a 09 09 7b 0a 09 09 09 73 74 72 6e 63 70 | ..........strncp |
00000320 79 28 66 69 6c 65 6e 61 6d 65 2c 20 61 72 67 76 | y.filename..argv |
00000330 5b 31 5d 2c 20 4d 41 58 5f 46 49 4c 45 4e 41 4d | .....MAX.FILENAM |
00000340 45 5f 4c 45 4e 20 29 3b 0a 09 09 7d 0a 09 09 0a | E.LEN........... |
00000350 09 09 65 6c 73 65 0a 09 09 7b 0a 09 09 09 70 72 | ..else........pr |
00000360 69 6e 74 66 28 22 50 6c 65 61 73 65 20 65 6e 74 | intf..Please.ent |
00000370 65 72 20 61 20 66 69 6c 65 6e 61 6d 65 3a 20 22 | er.a.filename... |
00000380 29 3b 0a 09 09 09 69 66 28 20 73 63 61 6e 66 28 | ......if..scanf. |
00000390 22 25 32 39 73 22 2c 20 66 69 6c 65 6e 61 6d 65 | ....s...filename |
000003a0 29 20 21 3d 20 31 20 29 0a 09 09 09 7b 0a 09 09 | ................ |
000003b0 09 09 66 70 72 69 6e 74 66 28 20 73 74 64 65 72 | ..fprintf..stder |
000003c0 72 2c 20 22 73 63 61 6e 66 20 74 6f 20 67 65 74 | r...scanf.to.get |
000003d0 20 66 69 6c 65 6e 61 6d 65 20 66 72 6f 6d 20 75 | .filename.from.u |
000003e0 73 65 72 20 66 61 69 6c 65 64 5c 6e 22 20 29 3b | ser.failed.n.... |
000003f0 0a 09 09 09 09 65 78 69 74 28 20 45 58 49 54 5f | .....exit..EXIT. |
00000400 46 41 49 4c 55 52 45 20 29 3b 0a 09 09 09 7d 0a | FAILURE......... |
00000410 09 09 7d 0a 0a 09 09 46 49 4c 45 20 2a 66 70 20 | .......FILE..fp. |
00000420 3d 20 66 6f 70 65 6e 28 66 69 6c 65 6e 61 6d 65 | ..fopen.filename |
00000430 2c 20 22 72 62 22 29 3b 0a 09 09 69 66 28 20 21 | ...rb......if... |
00000440 20 66 70 20 29 0a 09 09 7b 0a 09 09 09 70 65 72 | .fp..........per |
00000450 72 6f 72 28 20 22 66 6f 70 65 6e 20 66 6f 72 20 | ror...fopen.for. |
00000460 69 6e 70 75 74 20 66 69 6c 65 20 66 61 69 6c 65 | input.file.faile |
00000470 64 22 29 3b 0a 09 09 09 65 78 69 74 28 20 45 58 | d.......exit..EX |
00000480 49 54 5f 46 41 49 4c 55 52 45 20 29 3b 0a 09 09 | IT.FAILURE...... |
00000490 7d 0a 0a 09 09 66 73 65 65 6b 28 20 66 70 2c 20 | .....fseek..fp.. |
000004a0 30 2c 20 53 45 45 4b 5f 45 4e 44 20 29 3b 0a 09 | ...SEEK.END..... |
000004b0 09 6c 6f 6e 67 20 66 69 6c 65 6c 65 6e 20 3d 20 | .long.filelen... |
000004c0 66 74 65 6c 6c 28 20 66 70 20 29 3b 0a 09 09 70 | ftell..fp......p |
000004d0 72 69 6e 74 66 28 22 4c 65 6e 67 74 68 20 6f 66 | rintf..Length.of |
000004e0 20 66 69 6c 65 20 69 73 3a 20 25 6c 64 5c 6e 22 | .file.is...ld.n. |
000004f0 2c 20 66 69 6c 65 6c 65 6e 29 3b 0a 09 09 66 73 | ..filelen.....fs |
00000500 65 65 6b 28 20 66 70 2c 20 30 2c 20 53 45 45 4b | eek..fp.....SEEK |
00000510 5f 53 45 54 20 29 3b 0a 09 09 0a 09 09 62 79 74 | .SET.........byt |
00000520 65 20 66 69 6c 65 64 61 74 61 5b 20 31 36 20 5d | e.filedata...... |
00000530 3b 0a 09 09 73 69 7a 65 5f 74 20 62 79 74 65 73 | ....size.t.bytes |
00000540 52 65 61 64 3b 0a 09 09 77 68 69 6c 65 28 20 28 | Read....while... |
00000550 20 62 79 74 65 73 52 65 61 64 20 3d 20 66 72 65 | .bytesRead...fre |
00000560 61 64 28 20 66 69 6c 65 64 61 74 61 2c 20 31 2c | ad..filedata.... |
00000570 20 73 69 7a 65 6f 66 20 66 69 6c 65 64 61 74 61 | .sizeof.filedata |
00000580 2c 20 66 70 20 29 29 20 3e 20 30 20 29 0a 09 09 | ..fp............ |
00000590 7b 0a 09 09 09 2f 2f 70 72 69 6e 74 66 28 20 22 | .......printf... |
000005a0 62 79 74 65 73 52 65 61 64 3a 20 25 7a 75 5c 6e | bytesRead...zu.n |
000005b0 22 2c 20 62 79 74 65 73 52 65 61 64 20 29 3b 0a | ...bytesRead.... |
000005c0 09 09 09 70 72 69 6e 74 69 74 28 20 62 79 74 65 | ...printit..byte |
000005d0 73 52 65 61 64 2c 20 66 69 6c 65 64 61 74 61 20 | sRead..filedata. |
000005e0 29 3b 0a 09 09 7d 0a 09 09 0a 09 09 66 63 6c 6f | ............fclo |
000005f0 73 65 28 20 66 70 20 29 3b 0a 09 7d 0a | se..fp....... |
Note: when the final read is less than 16 bytes, you might want to fill out the last line of the input with spaces
Note you might want to modify the if( isalpha() )
to if( isprint() )
so other than the letters a..z and A..Z are printed