Search code examples
clinuxfopenelffwrite

Cant edit a binary program using fwrite and writing an int?


I'm trying to make a program to write a number into two different file(binary elf file) offsets using fwrite and fseek but both seems to report writing and seeking correctly but objdump -s 0x2db0 -n 0x16 testseems to show no change. fwrite and fseek called as:

error = fwrite((void*)&value, sizeof(value), 1, file);
seek_error = fseek(file, offset, SEEK_SET);

whole program is executed like bellow and is supposed to write 0x119e at offset 0x2db0 and 0x01:

./patch test 0x01 0x2db0 0x119e

so instead of seeing 119e at both offsets when running objdump no change seems to happen at all.

whole Source code is:(mostly checking for functions return values)

#include <stdio.h>
#include <stdlib.h>
#include <zconf.h>
#include <errno.h>

int main(int argc, char *argv[]){
    long error, seek_error;
    long value, offset;

    if (argc < 5){
        fprintf(stderr, "Incorrect arg number\n");
        exit(1);
    }

    FILE* file = fopen(argv[1], "ab");
    if (file == NULL){
        fprintf(stderr, "Error openning File\n");
        perror("fopen() :");
        exit(1);
    }
    printf("\t\t File opened successfully\n");

    value = strtol(argv[4], NULL, 16); /* convert target value to int */
    if (value == LONG_MIN || value == LONG_MAX){
        fprintf(stderr, "Error calling strtol\n");
        perror("strtol() :");
        exit(1);
    }

    offset = strtol(argv[2], NULL, 16);
    printf("offset is %ld\n", offset);
    if (offset == LONG_MIN || offset == LONG_MAX) {
        fprintf(stderr, "Error calling strtol during offset\n");
        perror("strtol() :");
        exit(1);
    }

    seek_error = fseek(file, offset, SEEK_SET); /* From start go to end*/
    if (seek_error != 0){
        fprintf(stderr, "Error calling fseek\n");
        perror("fseek(): ");
        exit(1);
    }
    printf("File position is: 0x%lx\n", ftell(file));

    error = fwrite((void*)&value, sizeof(value), 1, file);
    if (error != 1){
        fprintf(stderr, "Error calling write\n");
        perror("write() :");
        exit(1);
    }
    printf("Number of bytes written %ld\n", error);

    offset = strtol(argv[3], NULL, 16);
    printf("offset is %ld\n", offset);
    if (offset == LONG_MIN || offset == LONG_MAX) {
        fprintf(stderr, "Error calling strtol during scond offset\n");
        perror("strtol() :");
        exit(1);
    }

    seek_error = fseek(file, offset, SEEK_SET);  /* Seek to the new offset */
    if (seek_error != 0){
        fprintf(stderr, "Error calling second fseek\n");
        perror("fseek(): ");
        exit(1);
    }
    printf("File position is: 0x%lx\n", ftell(file));

    error = fwrite((void*)&value, sizeof(value), 1, file);
    if (error != 1){
        fprintf(stderr, "Error calling write\n");
        perror("write() :");
        exit(1);
    }
    printf("Number of bytes written %ld\n", error);

    fflush(file);   /* flush changes not nesessecarly */
    error = fclose(file);
    if (error != 0){
        fprintf(stderr, "error closing file\n");
        perror("close() :");
        exit(1);
    }
}

Solution

  • You're opening the file in append mode with fopen(argv[1], "ab"). So all writes are done at the end of the file, ignoring the position you seeked to.

    Use fopen(argv[1], "rb+") instead. r means to open it in read mode, so the file isn't emptied first, and + means that writing is also allowed.