1

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

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

2 Comments

Ok, I'll use memcmp instead of _ strstr_. Regarding the second issue, which I have noticed from the beginning, is there a way to overcome it? thanks
This case only can occur at the end of buffer. Maybe fill variable int howManyCharsFitAtEnd (usually zero, kind of marker declared out of loop), and on the beginning on new buffer use accordingly if not zero

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.