self modifying code 自修改程序

Posted on 2009-10-22 10:35 王小明 阅读(320) 评论(0)  编辑 收藏 引用
程序在运行过程序中,修改自己的代码段内存,改变了原先的代码指令。
这种编程思路在某些方面相当实用,能很好的提高程序的效率。
比如一段代码在第一次运行后就不再使用了,但每次都要对其进行判断,像某些模拟器程序中,这种判断就会占去很多的效率,如果使用这种自修改思路,即把某些只要执行一次的代码在执行过后除去,那将很好的提高了效率。

下面是一个在网上DOWNLOAD的一个示例程序,我在 Linux 2.6.28 , gcc 4.3.3 环境测试成功。

$ cat -n smc.c
     1    /*
     2     * Self Modifying Code  smc.c
     3     */
     4    
     5    #include <stdio.h>
     6    #include <stdlib.h>
     7    #include <unistd.h>
     8    #include <sys/mman.h>
     9    #include <errno.h>
    10    #include <string.h>
    11    
    12    /*    gcc is oblivious to asm level so we have to spell out
    13        our intentions.. it's an ugly hack. if you know of
    14        a proper way to do it in pure C please tell me. */
    15    
    16    extern char injectHere;
    17    extern char injectionStart;
    18    extern char injectionEnd;
    19    
    20    void dummyTextContext( void )
    21    {
    22        /*    sometimes gcc is just too smart.. in an ideal world
    23            we would write smthng like (*(&exit))( 42 ); and get
    24            an indirect call (via absolute address). anyway,
    25            we don't get that so we have to make one pointer for
    26            every type of function we want to call */
    27    
    28        int (*callPrintf)( const char *format, ... );
    29        void (*callExit)( int ); /* man 3 printf exit */
    30    
    31        asm volatile( "injectionStart:" );
    32    
    33        /*    do what you like here but keep it relocatable
    34            fire up objdump, gdb or whatever to check what you get */
    35    
    36        (*(callPrintf=&printf))( "Hello :-)\n" );
    37        (*(callPrintf=&printf))( "No endless loop here!\n" );
    38    
    39        (*(callExit=&exit))( 42 ); /* the meaning of life (for this proggie anyway..) */
    40    
    41        asm volatile( "injectionEnd:" );
    42    }
    43    
    44    int main( void )
    45    {
    46        /*    it's fairly safe to assume page is 2^N,
    47            now.. let's find us a page to bash >:*/
    48    
    49        unsigned page = (unsigned)&injectHere & ~( getpagesize() - 1 );
    50    
    51        /*    chmod u=rwx page ;-) */
    52    
    53        if( mprotect( (char*)page, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC ) )
    54        {
    55            perror( "mprotect failed" );
    56            exit( errno );
    57        }
    58    
    59    endlessLoop:
    60    
    61        asm volatile( "injectHere:" );    /* ground zero */
    62    
    63        /*    a few stats to ease debugging (and some code to fill our loop too) */
    64    
    65        printf( "PAGE(0x%x): cp <0x%x>[0..%u] <0x%x>\n",
    66                page, (int)&injectionStart, &injectionEnd - &injectionStart, (int)&injectHere );
    67    
    68        /*    inject some */
    69    
    70        memcpy( &injectHere, &injectionStart, &injectionEnd - &injectionStart );
    71    
    72        goto endlessLoop;
    73    
    74        return 0;
    75    }
只有注册用户登录后才能发表评论。