文章目录
- 1 代码
- 2 思想
1 代码
```c
#include
int main() { char *s = "#include%cint main() { char *s = %c%s%c; printf( s, 10, 34, s, 34 ); return 0; }" ; printf( s, 10, 34, s, 34 ); return 0; }
结果:(由于长度原因不能一次截图完整)
右边的部分
C++版本:
#include
#include
using namespace std;
int main (){string a="#includeT#include Tusing namespace std;Tint main (){string a=;a[19]=a[37]=a[58]=10;cout< ;a[19]=a[37]=a[58]=10;cout<<a.substr(0,80)<<(char)34;a[19]=a[37]=a[58]=84;cout<<a<<(char)34<<a.substr(80);return 0;}
2 思想
提到自我打印程序,很典型的就是病毒,病毒的起源“磁心大战”,就是各个程序在存储器中复制自己抢地盘。
其实自打印的程序很具有模版化,可以分成两部分:AB。
其中
- A的输出就是B的程序文字。
- 要求:
- 通过它的输出即要得到A的程序文字,
- 也能得到B的程序文字。
- B部分可以得到A部分的输出,同时可以根据A部分的输出得到A部分的程序文字,这样B便可以把AB的程序文字联合起来,printf即可。
而在写A的时候,通常通过一个字符串赋值完成,但是这个赋值需要等到B部分完成之后才能真正完成。首先A将自身包含,然后写B部分,然后在A中将B包含。
#include <iostream>
#include <string>
using namespace std;
int main (){string a="#include T#include Tusing namespace std;Tint main (){string a=;a[19]=a[37]=a[58]=10;cout<<a.substr(0,80)<<(char)34;a[19]=a[37]=a[58]=84;cout<<a<<(char)34<<a.substr(80);return 0;}";a[19]=a[37]=a[58]=10;cout<<a.substr(0,80)<<(char)34;a[19]=a[37]=a[58]=84;cout<<a<<(char)34<<a.substr(80);return 0;}
这个例子中(换行了,方便观察):
a[19]=10;a[37]=10;a[58]=10;
作用是将字符"T"换为回车符号,
a[19]=84;a[37]=84;a[58]=84;
作用是打印完第一部分后还原为"T"。
string a的值产生了A,B的代码,
- A:
a.substr(0,80)<<(char)34<<....<<(char)34
(从开头到a定义之后的); - B:
a.substr(80)
则是B部分(从cout到结束)
备注:
- char(34)为双引号
参考:
作者:phylips@bmy