0

I use the function fgetc to read each byte of a file, and then write it with printf.

I just noticed that sometimes, fgetc just miss some bytes, when I compare my result with a hex editor.

For example, the first mistake starts around the 118th byte, and a lot of other mistakes randomly ...

Somebody ever experienced this?

This is the code (Windows)

char main(int argc, char* argv[]) {
    FILE* fdIn;
    FILE* fdOut;
    long size = 0;
    long i = 0;
    char c = 0;
    if (argc == 3) {
        if ((fdIn = fopen(argv[1], "rt")) == NULL) {
            printf("FAIL\n");
            return 0;
        }
        if ((fdOut = fopen(argv[2], "w+")) == NULL) {
            printf("FAIL\n");
            return 0;
        }
        fseek(fdIn, 0L, SEEK_END);
        size = ftell(fdIn);
        fseek(fdIn, 0L, 0);
        fprintf(fdOut, "unsigned char shellcode[%ld] = {", size);
        while (i < size) {
            c = fgetc(fdIn);
            if (!(i % 16))
                fprintf(fdOut, "\n\t");
            fprintf(fdOut, "0x%02X", (unsigned char)c);
            if (i != size - 1)
                fprintf(fdOut, ", ");
            i++;
        }
        fprintf(fdOut, "\n};\n");
        fclose(fdIn);
        fclose(fdOut);
        printf("SUCCESS");
        system("PAUSE");
    }
    return 0;
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 2
    Open the file in binary mode. – chux - Reinstate Monica Oct 20 '16 at 22:55
  • 3
    Show us your code, your test data, the expected result and the actual result. – NineBerry Oct 20 '16 at 22:55
  • Are you working on WIndows? Are the missing characters CR (`\r`, `\012`)? Or perhaps ^Z (`\032`)? Did you open the file in text mode or binary mode? – Jonathan Leffler Oct 20 '16 at 23:01
  • It probably isn't fair to ask you, Adam (so this is really aimed at the world in general), but I'm left wondering: why do people insist on use `fgetc()` instead of `getc()`? There is a strong tendency here on SO for novice questions to use `fgetc()` for single character output and to use `printf()` for all output, even when `putchar()` would do the job admirably. Ah well, it's probably inscrutable — but it is odd to me. – Jonathan Leffler Oct 20 '16 at 23:04
  • That's not the complete code (`FILE` is undeclared). – melpomene Oct 20 '16 at 23:04
  • `char` is the wrong return type for `main`. – melpomene Oct 20 '16 at 23:04
  • `argv[1]` already is of type `char *`. Why cast it to `(char *)` again? – melpomene Oct 20 '16 at 23:05
  • `fgetc` doesn't return `char` for a reason. – melpomene Oct 20 '16 at 23:06
  • Congratulations: I've seen a lot of return types for `main()`, but I think this is the first time I've seen `char` used. See [What should `main()` return in C and C++](http://stackoverflow.com/questions/204476/) for more information. – Jonathan Leffler Oct 20 '16 at 23:06
  • Why open `fdOut` in read/write mode if you never read from it? – melpomene Oct 20 '16 at 23:08
  • 1
    You could just output `unsigned char shellcode[] = {`; that way you don't need `size` anymore. – melpomene Oct 20 '16 at 23:10

1 Answers1

2

Open the file in binary mode.

// if ((fdIn = fopen((char*)argv[1], "rt")) == NULL) { 
//                                 >.< 
if ((fdIn = fopen((char*)argv[1], "rb")) == NULL) {

In text mode, and likely a Windows based machine given the "rt", a '\r', '\n' pair is certainly translated into '\n'. IAC, no translations are needed for OP's goal of a hex dump.


2nd issue: fgetc() returns an int in the range of unsigned char or EOF. Use type int to distinguish EOF from all data input.

// char c = 0;
int c = 0;
...
c = fgetc(fdIn);

// also add
if (c == EOF) break;
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256