我继承了一个在Unix上有“编译”perl脚本的环境。是否有可能对其进行反编译,反向工程(无论是什么术语),并从编译的目标代码中获取源代码?
可能不可能,但我想我会问而不是假设。
谢谢, -Kevin。
答案 0 :(得分:13)
省略了已经涵盖的字节码后端tchrist并且只讨论C
后端,所有perlcc
所做的就是将编译的perl程序的optree转换为C程序,然后编译它。那个C程序在运行时会将该optree重构为内存,并且基本上就像Perl一样执行它。关键在于加速常规perl代码的编译时间。
然后在PL_main_root
全局变量中提供您的程序的optree。我们已经有一个名为B::Deparse
的模块,它可以使用optrees并将它们转换为大致相当于编译optree的原始代码的源代码。碰巧有一个compile
方法返回一个coderef,当执行时,它会打印PL_main_root
的解析结果。
还有C函数Perl_eval_pv
,您可以使用它来评估C空间中的Perl片段。
$ echo 'print 42, "\\n"' > foo.pl
$ perl foo.pl
42
$ perlcc foo.pl
$ ./a.out
42
$ gdb a.out
...
(gdb) b perl_run
Breakpoint 1 at 0x4570e5: file perl.c, line 2213.
(gdb) r
...
Breakpoint 1, perl_run (my_perl=0xa11010) at perl.c:2213
(gdb) p Perl_eval_pv (my_perl, "use B::Deparse; B::Deparse->compile->()", 1)
print 42, "\n";
$1 = (SV *) 0xe47b10
当然,通常的B :: Deparse警告适用,但这肯定对逆向工程很方便。实际上,在大多数情况下,重建原始源代码是不可能的,即使它适用于上面的例子。
你必须做的确切的gdb魔法才能让B :: Deparse给你一些合理的东西,这在很大程度上取决于你的perl。我正在使用带有ithreads的perl,因此具有多样性。这就是我传递my_perl
变量的原因。其他perls可能不需要那样。另外,如果有人剥离了perlcc编译的二进制文件,事情会变得有点困难,但同样的技术仍然会有效。
此外,您可以使用它来编译任何您可以在程序执行期间随时获得的任何选项。看看B :: Deparse的compile sub并做类似的事情,除了为你想要转储的任何optree而不是B
提供B::main_root
对象。
同样的事情适用于所提到的perlcc的字节码后端。我不完全确定名为CC
的优化C后端。
答案 1 :(得分:10)
哦,我的!
如果且仅当通过perlcc -B
将其编译为可执行字节代码时,可以然后以与B :: Deparse相同的方式对其进行解编译。你会收回那些没有通过这种方式优化的来源。它可能看起来有点滑稽,但它将是一个等效的程序。
但是,如果它被完全编译成C代码,然后是汇编程序和机器语言,并通过ld
运行正确的a.out
文件,那么你将无法做任何事情那。这就像试图反汇编/bin/cat
。
好吧,你可以把它拆开,但那里没有快乐。即使你可以获得原始的,生成的C代码 - 你不能 - 它实际上是无法使用的。
我想你可能会在其上运行 strings (1),看看是否有任何有用的内容留在永久性的某个地方,但我不会指望它。
对不起。
答案 2 :(得分:0)
使用7-zip。右键单击exe文件,然后执行7zip>打开存档,然后获取perl文件。