Anelito
Anelito

Reputation: 212

Replace string in binary file

I am trying to write a *nix program that copies itself and replaces a string inside the binary. The copy process doesn't seem to work though.

Here's the code:

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>

#define BUFSIZE 10
#define FILENAME "token"

void findstring(const char *exe, const char* str)
{
    char buf[BUFSIZE];
    int line_num = 1;
    int i = 0, find_result = 0;
    FILE *fp = fopen(exe, "rb");
    if(fp == NULL)
        exit(-1);

    FILE *out = fopen("out", "wb");
    if(out == NULL)
        exit(-1);

    while(fgets(buf, BUFSIZE, fp) != NULL) {
        if((strstr(buf, str)))
        {
            printf("A match found on line: %d\n", line_num);
            printf("\n%s\n", buf);
            find_result++;

            // reverse "token" string in the output
            for(i = 0; i< BUFSIZE; i++)
            {
                if(strstr(&buf[i], "t") != NULL)
                    buf[i] = 'n';
                else if(strstr(&buf[i], "o") != NULL)
                    buf[i] = 'e';
                else if(strstr(&buf[i], "k") != NULL)
                    buf[i] = 'k';
                else if(strstr(&buf[i], "e") != NULL)
                    buf[i] = 'o';
                else if(strstr(&buf[i], "n") != NULL)
                    buf[i] = 't';
            }
        }
        line_num++;

        fputs(buf, out);
    }

    if(find_result == 0) {
        printf("\nSorry, couldn't find a match.\n");
    }

    fclose(fp);
    fclose(out);
}

int main(int argc, char **argv, char **envp)
{
//    argv[1] = FILENAME;

    char buf[1024];
    int fd, rc;

    findstring(argv[0], "token");

    if(argc == 1) {
        printf("\n\n%s [file to read]\n\n", argv[0]);
        exit(1);
    }

    printf("FILENAME macro = %s", FILENAME);

    if(strstr(argv[1], "token") != NULL) {
        printf("\n\nYou may not access '%s'\n\n", argv[1]);
        exit(2);
    }

    fd = open(argv[1], O_RDONLY);
    if(fd == -1) {
        printf("\n\nUnable to open %s\n\n", argv[1]);
        exit(3);
    }

    rc = read(fd, buf, sizeof(buf));

    if(rc == -1) {
        printf("\n\nUnable to read fd %d\n\n", fd);
        exit(4);
    }

    write(1, buf, rc);

    return 0;
}

"Token" string should be reversed in the output binary ("nekot"), with the findstring function responsible of performing this task. It is also worth noting that the number of matches found strictly depends on the BUFSIZE constant.

What is this code missing? Thanks

Upvotes: 1

Views: 2053

Answers (2)

Jacek Cz
Jacek Cz

Reputation: 1906

1. All C style string functions break at first '\0' . So if buf contains null character before Your goal, will be never found.

if((strstr(buf, str))) { ... } 

I suggest loop with step one character (byte) coded by hand, or functions from family memXXXXcmp etc

  1. If Your token is over boundaries of two buffers (from two loo[ iterations), no comparison can fount is

Upvotes: 1

Chris Dodd
Chris Dodd

Reputation: 126243

consider what this does:

  if(strstr(&buf[i], "t") != NULL)
      buf[i] = 'n';

This will search the buffer starting at index i, and if the string "t" appears anywhere in the buffer, it will replace the first character with n. So if your buffer has

a string with token inside.

the first iteration of the for loop will change it to

n string with token inside.

as the loop proceeds you'll get

nnnnnnnnnnith token inside.

after 10 iterations and ultimately

nnnnnnnnnnnnnnnekooooooooo.

Other issues:

  • fgets reads a string up to a newline or up to BUFSIZE-1 characters. There may well be bytes that are equivalent to newline chars.
  • You're scanning through BUFSIZE bytes regardless of how many bytes you read.
  • fputs will write up to the first NUL byte. If there are NUL bytes anywhere in your input binary, stuff after the NUL in the buffer will be lost.

The above means you probably want to use fread/fwrite instead of fgets/fputs, and you want to carefully check return values for shot read or writes.

Upvotes: 1

Related Questions