找回密码
 欢迎注册
查看: 5485|回复: 7

[原创] 搜寻【自修改代码】的有趣例子

[复制链接]
发表于 2022-12-14 14:34:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
如果一段程序代码在运行的过程中修改了自己,并且在后续的运行过程中,执行了被修改过的代码段,我们称这种代码为“自修改代码”。

关于“自修改代码”,百科上有这样的描述:

3.png

目前大多数的编程语言,代码区、内存区和读写区都是分开的,不具有“自修改代码”这种特性。

我想探索的问题是:

如果代码区、内存区、读写区是同一个区域,会发生什么有意思的事情呢?

比如,百科里说这样就可以“制造病毒”了。你们能否找到或写出一段可以【制造病毒】的自修改代码呢?

除了“制造病毒”以外,自修改代码还有哪些有意思的行为呢?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2022-12-14 15:49:54 | 显示全部楼层
为了寻找有意思的例子,我仿照BF语言,定义了下面这种编程语言:

4_副本.png

注:上表的“指针”指的是内存指针。

正常情况下,代码区、输入区、输出区、内存区是分开的:

6.png

每执行一个字符,代码区的指针会右移一个字符(跳转除外)。

如果执行到读入指令,那么内存指针所指的字符就会被输入区的指针所指的字符覆盖,然后输入区的指针会右移一个字符;

如果执行到写入指令,那么内存指针所指的字符就会被拷贝到输出区的指针所指的地方,然后输出区的指针会右移一个字符。

我想探究一下,如果代码区、输入区、输出区、内存区是同一个区域,会有什么有意思的事情发生?

6.png

如果换成别的语言,会不会有更有意思的事情发生?

比如,能否让ChatGpt解析并枚举式地改进它自己的代码,

如果改进后更强了,就保留这一改进,否则改回去,它是不是就把自己越改越强了呢?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2022-12-15 09:09:54 | 显示全部楼层
如果换成C语言,我想到了“制造病毒”的一个例子,只需短短地一句“printf(...)”语句就能实现:

c6367b9e103c9a7df5c1ddc0f0094d39.png

由于写指针就在代码指针后面,每次运行一句“printf(...)”语句,下一行“printf(...)”代码就写好了,并且下一步就会执行到它。

这就使得“printf(...)”这段代码不断地自我复制,最终整个内存区(同时也是代码区和读写区)都被“printf(...)”这段病毒代码占满了。

你们还能不能举出别的有趣的例子呢?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2022-12-16 11:28:26 | 显示全部楼层
KeyTo9_Fans 发表于 2022-12-15 09:09
如果换成C语言,我想到了“制造病毒”的一个例子,只需短短地一句“printf(...)”语句就能实现:

不懂
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2022-12-16 11:37:29 | 显示全部楼层
JIT 算不算?

在Linux环境, JIT的流程大概是这样的.
1. 使用 mmap 函数,  分配一块内存, 属性为可读可写
2. 调用LLVM 生成一段二进制代码 (或用别的方法生成二进制代码)
3. 复制二进制代码 到mmap分配的内存块
4. 使用mprotect将块的权限从RW更改为RX,使其可执行但不再可写
5. 调用生成的代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2023-1-31 21:38:38 | 显示全部楼层
3楼的想法,实现起来是有技术难度的,这篇贴子的作者也在尝试解决这个问题:

https://tieba.baidu.com/p/8235648856

但经过吧友们的讨论,好像仍未实现代码的自修改……
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2023-2-1 08:59:05 | 显示全部楼层
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2023-2-1 10:56:08 | 显示全部楼层
看百度链接里面要求修改代码文件,这个可以比较简单实现,比如Linux下面的方案:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. int x=1;
  5. #define LSIZE 1024
  6. char line[LSIZE];

  7. int main(int argc, char *argv[])
  8. {
  9.         char fname[200];
  10.         FILE *f1,*f2;
  11.         sprintf(fname,"%s.c",argv[0]);
  12.         f1=fopen(fname,"r");
  13.         f2=fopen("tmpf","w");
  14.         while(fgets(line,LSIZE,f1)){
  15.                 if(strncmp(line,"int x=",6)==0){
  16.                         int d=atoi(line+6);
  17.                         fprintf(f2, "int x=%d;\n",d+1);
  18.                 }else{
  19.                         fprintf(f2,"%s",line);
  20.                 }
  21.         }
  22.         fclose(f1);
  23.         fclose(f2);
  24.         sprintf(line, "mv tmpf %s.c; gcc -O3 %s.c -o%s",argv[0],argv[0],argv[0]);
  25.         system(line);
  26.         printf("%d\n",x);
  27.         return 0;
  28. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-21 17:56 , Processed in 0.026450 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表