当您有混淆代码时,您需要清理物理布局、添加一些空白、添加必要的缩进,然后编译代码。来自编译器的警告会告诉你很多关于程序隐藏的一些东西。
First Cut 简化 - 添加空格
int i;
main()
{
for( ; i["]<i;++i){--i;}"];
read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
}
read(j,i,p)
{
write(j/p+p,i---j,i/i);
}
当使用gcc -Wall 编译程序时,我收到以下警告:
soc.c:2:1: warning: return type defaults to ‘int’ [enabled by default]
main()
^
soc.c: In function ‘main’:
soc.c:4:4: warning: implicit declaration of function ‘read’ [-Wimplicit-function-declaration]
for( ; i["]<i;++i){--i;}"]; read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
^
soc.c:4:50: warning: unknown escape sequence: '\o' [enabled by default]
for( ; i["]<i;++i){--i;}"]; read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
^
soc.c: At top level:
soc.c:7:1: warning: return type defaults to ‘int’ [enabled by default]
read(j,i,p)
^
soc.c: In function ‘read’:
soc.c:7:1: warning: type of ‘j’ defaults to ‘int’ [enabled by default]
soc.c:7:1: warning: type of ‘i’ defaults to ‘int’ [enabled by default]
soc.c:7:1: warning: type of ‘p’ defaults to ‘int’ [enabled by default]
soc.c:9:4: warning: implicit declaration of function ‘write’ [-Wimplicit-function-declaration]
write(j/p+p,i---j,i/i);
^
soc.c:9:17: warning: operation on ‘i’ may be undefined [-Wsequence-point]
write(j/p+p,i---j,i/i);
^
soc.c:9:17: warning: operation on ‘i’ may be undefined [-Wsequence-point]
soc.c:10:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
二次切割简化 - 去混淆
根据上述警告,可以将程序解混淆为:
int i;
void read(int j, char* i, int p);
void write(int j, char* i, int p);
int main()
{
for( ; i["]<i;++i){--i;}"];
read('-'-'-', , '/'/'/'));
return 0;
}
void read(int j, char* i, int p)
{
write(j/p+p, (i--) - j, 1);
}
以上版本没有编译器警告并且产生相同的输出。
三切简化 - 取消混淆更多
表达式i["]<i;++i){--i;}"] 用于运行循环14 次。就那么简单。可以简化为i < 14。
'-'-'-' 是0。
'/'/'/' 是1。
i++ + "hello, world!\n" 与s + i++ 相同,其中s 可以是char const* s = "hello, world!\n";
for 循环可以简化为:
char const* s = "hello, world!\n";
for( ; i < 14; read(0, s+i++, 1));
由于read中j的值始终为零,所以read的实现可以简化为:
void read(int j, char* i, int p)
{
write(0, (i--), 1);
}
表达式(i--) 可以简化为i,因为作为副作用的递减不会改变函数的工作方式。也就是说,上面的函数是:
void read(int j, char* i, int p)
{
write(0, i, 1);
}
当我们意识到参数j的值总是0并且参数p的值总是1时,我们可以将主函数中的for循环更改为:
for( ; i < 14; i++)
{
write(0, s+i, 1);
}
因此,整个程序可以简化为:
void write(int j, char const* i, int p);
int main()
{
int i = 0;
char const* s = "hello, world!\n";
for( ; i < 14; i++ )
{
write(0, s+i, 1);
}
return 0;
}
Fourth Cut Simplification - Make It Trivial
以上版本有一个硬编码号码14。那是s 中的字符数。因此,可以通过将程序更改为:
void write(int j, char const* i, int p);
int main()
{
write(0, "hello, world!\n", 14);
return 0;
}