Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
317 views
in Technique[技术] by (71.8m points)

self reference - C: How to change my own program in my program in runtime?

At runtime, either the assembler or machine code (which is it?) should be somewhere in RAM. Can I somehow get access to it, and read or even write to it?

This is just for educational purposes.

So, I just could compile this code. Am I really reading myself here?

#include <stdio.h>
#include <sys/mman.h>

int main() {
    void *p = (void *)main;
    mprotect(p, 4098, PROT_READ | PROT_WRITE | PROT_EXEC);
    printf("Main: %p
 Content: %i", p, *(int *)(p+2));
    unsigned int size = 16;
    for (unsigned int i = 0; i < size; ++i) {
        printf("%i ", *((int *)(p+i)) );
    }
}

Though, if I add

*(int*)p =4;

then it's a segmentation fault.


From the answers, I could construct the following code which modifies itself during runtime:

#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>

void * alignptr(void * ptr, uintptr_t alignment) {
    return (void *)((uintptr_t)ptr & ~(alignment - 1));
}

// pattern is a 0-terminated string
char* find(char *string, unsigned int stringLen, char *pattern) {
    unsigned int iString = 0;
    unsigned int iPattern;
    for (unsigned int iString = 0; iString < stringLen; ++iString) {
        for (iPattern = 0;
            pattern[iPattern] != 0
            && string[iString+iPattern] == pattern[iPattern];
            ++iPattern);
        if (pattern[iPattern] == 0) { return string+iString; }
    }
    return NULL;
}

int main() {
    void *p = alignptr(main, 4096);
    int result = mprotect(p, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
    if (result == -1) {
        printf("Error: %s
", strerror(errno));
    }

    // Correct a part of THIS program directly in RAM
    char programSubcode[12] = {'H','e','l','l','o',
                                ' ','W','o','r','l','t',0};
    char *programCode = (char *)main;
    char *helloWorlt = find(programCode, 1024, programSubcode);
    if (helloWorlt != NULL) {
        helloWorlt[10] = 'd';
    }   
    printf("Hello Worlt
");
    return 0;
}

This is amazing! Thank you all!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In principle it is possible, in practice your operating system will protect itself from your dangerous code!

Self-modifying code may have been regarded as a "neat-trick" in the days when computers had very tiny memories (in the 1950's). It later (when it was no longer necessary) came to be regarded as bad practice - resulting in code that was hard to maintain and debug.

In more modern systems (at the end of the 20th Century) it became a behaviour indicative of viruses and malware. As a consequence all modern desktop operating systems disallow modification of the code space of a program and also prevent execution of code injected into data space. Modern systems with an MMU can mark memory regions as read-only, and not-executable for example.

The simpler question of how to obtain the address of the code space - that is simple. A function pointer value for example is generally the address of the function:

int main()
{
    printf( "Address of main() = %p
", (void*)main ) ;
}

Note also that on a modern system this address will be a virtual rather then physical address.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...