跳转到内容

软件工程/工具/混淆介绍

来自维基教科书,开放的书籍,开放的世界

混淆代码是指经过处理,使其对人类难以理解的源代码或机器代码。程序员可能会故意混淆代码以隐藏其目的(安全通过模糊性)或其逻辑以防止篡改、阻止逆向工程,或者作为阅读源代码者的谜题或娱乐性挑战。称为混淆器的程序使用各种技术将可读代码转换为混淆代码。代码混淆本质上不同于硬件混淆,在硬件混淆中,电路的描述和/或结构被修改以隐藏其功能。

某些语言可能比其他语言更容易混淆。[1][2] C,[3] C++[4] 和 Perl[5] 就是一些例子。

娱乐性混淆

[编辑 | 编辑源代码]

编写和阅读混淆的源代码可以成为程序员的脑筋急转弯。许多编程竞赛会奖励最具创意的混淆代码:国际混淆 C 代码竞赛、混淆 Perl 竞赛和 国际混淆 Ruby 代码竞赛

混淆的类型包括简单的关键字替换、使用或不使用空格来创建艺术效果,以及自生成或高度压缩的程序。

简短的混淆 Perl 程序可能用在 Perl 程序员的签名中。这些是 JAPH(“Just another Perl hacker”)。[需要引用]

这是国际混淆 C 代码竞赛的获奖作品 [6],由 Ian Phillipps 于 1988 年编写 [7],后来由 Thomas Ball 逆向工程。 [8]

/*
  LEAST LIKELY TO COMPILE SUCCESSFULLY:
  Ian Phillipps, Cambridge Consultants Ltd., Cambridge, England
*/

#include <stdio.h>
main(t,_,a)
char
*
a;
{
	return!

0<t?
t<3?

main(-79,-13,a+
main(-87,1-_,
main(-86, 0, a+1 )

+a)):

1,
t<_?
main(t+1, _, a )
:3,

main ( -94, -27+t, a )
&&t == 2 ?_
<13 ?

main ( 2, _+1, "%s %d %d\n" )

:9:16:
t<0?
t<-72?
main( _, t,
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#;\
#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;\
q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; \
r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#\
\
n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;\
{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;\
#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/")
:
t<-50?
_==*a ?
putchar(31[a]):

main(-65,_,a+1)
:
main((*a == '/') + t, _, a + 1 )
:

0<t?

main ( 2, 2 , "%s")
:*a=='/'||

main(0,

main(-61,*a, "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry")

,a+1);}

这是一个 C 程序,编译并运行后会生成《圣诞节的十二天》的 12 节。它以编码形式包含了诗歌所需的全部字符串。

下面的例子是同年非获奖作品,展示了空格的创造性运用;它生成任意长度的迷宫 [9]

char*M,A,Z,E=40,J[40],T[40];main(C){for(*J=A=scanf(M="%d",&C);
--            E;             J[              E]             =T
[E   ]=  E)   printf("._");  for(;(A-=Z=!Z)  ||  (printf("\n|"
)    ,   A    =              39              ,C             --
)    ;   Z    ||    printf   (M   ))M[Z]=Z[A-(E   =A[J-Z])&&!C
&    A   ==             T[                                  A]
|6<<27<rand()||!C&!Z?J[T[E]=T[A]]=E,J[T[A]=A-Z]=A,"_.":" |"];}

现代 C 编译器不允许覆盖常量字符串,可以通过将 "*M" 更改为 "M[3]" 并省略 "M=" 来避免这种情况。

JAPH 的一个例子

@P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{
@p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=2)+=$f=!fork;map{$P=$P[$f^ord
($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&
close$_}%p;wait until$?;map{/^r/&&<$_>}%p;$_=$d[$q];sleep rand(2)if/\S/;print

这个程序会慢慢地显示文本“Just another Perl / Unix hacker”,一次显示多个字符,并带有延迟。可以在 这里 找到解释。

可以在 Python 官方编程 FAQ 中找到一些 Python 示例。

混淆的缺点

[编辑 | 编辑源代码]

充其量,混淆只会让逆向工程一个程序变得费时,但并非不可能。 [10]

混淆软件

[编辑 | 编辑源代码]

存在各种各样的工具来执行或协助代码混淆。这些工具包括由学者创建的实验性研究工具、业余爱好者工具、由专业人士编写的商业产品以及开源软件。还存在反混淆工具,试图执行逆向转换。

虽然大多数商业混淆解决方案通过转换程序源代码[11][12],或 Java[13] 和 .NET[14] 使用的平台无关字节码来工作,但还有一些工具可以与 C 和 C++[15][16] - 通常编译为本机代码的语言一起工作。

参考文献

[编辑 | 编辑源代码]
[编辑 | 编辑源代码]
华夏公益教科书