如何对使用perlcc编译的Perl程序进行逆向工程?

sou*_*ser 8 perl compilation

我继承了一个在Unix上有"编译"perl脚本的环境.是否可以反编译,反向工程(无论术语是什么),并从编译的目标代码中获取源代码?

可能不可能,但我想我会问而不是假设.

谢谢,-Kevin.

raf*_*afl 13

抛弃字节码后端tchrist已经涵盖并且只讨论C后端,所有的perlcc工作都是将编译的perl程序的optree转换为C程序,然后编译它.那个C程序在运行时会将该optree重构为内存,并且基本上就像Perl一样执行它.这一点实际上只是为了加快常规perl代码的编译时间.

然后,可以在PL_main_root全局变量中使用您的程序的optree .我们已经有一个名为的模块B::Deparse,它可以使用optrees并将它们变成源代码,这些源代码大致相当于编译optree的原始代码.碰巧有一个compile方法返回一个coderef,它会在执行时打印出deparse结果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
Run Code Online (Sandbox Code Playgroud)

当然,通常的B :: Deparse警告适用,但这肯定对逆向工程很方便.实际上,在大多数情况下,重建原始源代码是不可能的,即使它适用于上述示例.

你需要做的确切的gdb魔法才能让B :: Deparse给你一些合理的东西,这在很大程度上取决于你的perl.我正在使用带有ithreads的perl,因此具有多样性.这就是我传递my_perl变量的原因.其他perls可能不需要那样.此外,如果有人剥离了perlcc编译的二进制文件,事情会变得更加困难,但同样的技术仍然有效.

此外,您可以使用它来编译任何您可以在程序执行期间随时获得的任何选项.看看B :: Deparse的compile sub并做类似的事情,除了为B你想要转储的任何optree 提供一个对象,而不是B::main_root.

同样的事情适用于所提到的perlcc的字节码后端.我不完全确定优化的C后端被称为CC.


tch*_*ist 10

天啊!

如果且仅当它是通过编译成可执行的字节码perlcc -B,你那么uncompile用同样的方式B :: Deparse一样.你会收回那些没有通过这种方式优化的来源.它可能看起来有点滑稽,但它将是一个等效的程序.

但是,如果它被完全编译成C代码,然后由汇编程序和机器语言编译并运行ld以获得正确的a.out文件,那么您将无法执行此类操作.这就像试图拆解一样/bin/cat.

好吧,你可以把它拆开,但那里没有快乐.即使你可以得到原始的,生成的C代码 - 你不能 - 它实际上是无法使用的.

我想你可能会在它上面运行字符串(1),看看是否有任何有用的东西留在永久性的某个地方,但我不会指望它.

抱歉.