程序的自我改写

来源:互联网 发布:java反射机制原理 编辑:程序博客网 时间:2024/05/17 04:47
曾经,程序的自动改写是每个黑客必备的知识,因为这样可以有效的节约内存,下面是在现代的GNU/Linux 操作系统上实现的程序自我改写。
列一下环境:

speller@SHELL-LAB:~/code/c$ egrep "model name" /proc/cpuinfo | uniq -c
      2 model name      : Pentium(R) Dual-Core  CPU      E6300  @ 2.80GHz
speller@SHELL-LAB:~/code/c$ uname -sr
Linux 2.6.35.10-smp
speller@SHELL-LAB:~/code/c$ gcc --version | grep GCC
gcc (GCC) 4.4.4
speller@SHELL-LAB:~/code/c$


上代码:
  1. /*
  2.  * 文件名: self-modification.c
  3.  * 备注: 一个可以修改自身代码的小程序 ;p
  4.  */
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <sys/mman.h>

  8. void func (void);

  9. int main
  10. (int argc, char *argv[]) {
  11.     
  12.     int count = 0;

  13.     for (count = 0; count < 3; ++count) {
  14.         printf ("第<%d>次执行函数func:\n", count+1);
  15.         func ();
  16.     }

  17.     return 0;
  18. }

  19. void func
  20. (void) {

  21.     __asm__ __volatile__ (
  22.         "slot:\n"
  23.         "nop\nnop\n" /* 这两个nop 指令用来为下面的自动改写留出位置 */
  24.         "after_slot:\n"
  25.     );

  26.     puts ("\t你只能在第<1>次执行函数func 的时候看到这条消息\n"
  27.           "\t\t——因为程序对自身的代码进行了修改。\n");
  28.     
  29.     /* 将函数func 的堆栈属性设置为可读写、可执行 */
  30.     int pagesize = (int)sysconf (_SC_PAGESIZE);
  31.     char *p = (char *)((int)func & ~(pagesize - 1));
  32.     mprotect (p, pagesize * 10, PROT_READ | PROT_WRITE | PROT_EXEC);
  33.     
  34.     /* 进行自我改写 */
  35.     __asm__ __volatile__ (
  36.         ".byte 0xe8, 0, 0, 0, 0\n"     /* 0xe8 是call 指令,把popl 指令当作函数调用 */
  37.         "popl %%eax\n"                /* popl 出栈的是popl 指令自身的地址 */
  38.         "addl $20, %%eax\n"         /* 定位到第二个puts 函数 */
  39.         "subl $after_slot, %%eax\n"/* 得到第二个puts 函数相对于after_slot 标签的偏移 */
  40.         "shl $8, %%eax\n"             /* 这里是little endian 系统 */
  41.         "movb $0xeb, %%al\n"      /* 0xeb 是jmp 指令,%ax 里现在是 <jmp 偏移 >*/
  42.         "movw %%ax, slot"           /* 填充先前两个nop 指令预留出的空间 */
  43.         :
  44.         :
  45.         : "eax"
  46.     );

  47.     puts ("\t这条消息应该在每次调用函数func 的时候都被输出到stdout。\n");
  48.     
  49.     return;
  50. }
效果如下:
speller@SHELL-LAB:~/code/c$ gcc -o self-modification self-modification.c
speller@SHELL-LAB:~/code/c$ ./self-modification
第<1>次执行函数func:
        你只能在第<1>次执行函数func 的时候看到这条消息
                ——因为程序对自身的代码进行了修改。

        这条消息应该在每次调用函数func 的时候都被输出到stdout。

第<2>次执行函数func:
        这条消息应该在每次调用函数func 的时候都被输出到stdout。

第<3>次执行函数func:
        这条消息应该在每次调用函数func 的时候都被输出到stdout。

speller@SHELL-LAB:~/code/c$


程序自身对自身的指令进行修改,有点黑客帝国的味道,不是么 ;p
阅读(116) | 评论(0) | 转发(0) |
0

上一篇:S3C2440A IIC驱动(AT24c04)

下一篇:Linux常用命令(不定期更新)

相关热门文章
  • iOS学习之iOS沙盒(sandbox)文...
  • windows C 与 linux C区别?...
  • C++的异常处理
  • Linux V4L2驱动架构 一
  • java之路,IO操作
  • 承接自动化测试培训、外包、实...
  • Solaris PowerTOP 1.0 发布
  • For STKMonitor
  • busybox的httpd使用CGI脚本(Bu...
  • 项目小体会
  • 修改默认端口为222,centos自...
  • 用PHP做一个ftp登录页面...
  • Toad for Oracle工具,为什么在...
  • 本地win7安装vmw9系统winserv...
  • powermt config是所什么用的...
给主人留下些什么吧!~~
原创粉丝点击