当前位置:  开发笔记 > 编程语言 > 正文

逆向工程基于核心转储的Perl脚本

如何解决《逆向工程基于核心转储的Perl脚本》经验,为你挑选了1个好方法。

朋友的服务器(是的,真的.不是我的.)被打破了,我们发现了一个运行一些机器人代码的perl二进制文件.我们找不到脚本本身(可能是通过网络收到的eval'),但我们设法创建了perl进程的核心转储.

在核心上运行字符串给了我们一些提示(主机名,用户名/密码),但不是脚本的源代码.

我们想知道脚本能够做什么,所以我们想对perl解释器中运行的perl代码进行反向工程.

搜索周围,我发现最接近perl解编译器的是B :: Deparse模块,它似乎非常适合将解析树的字节码转换回可读代码.

现在,我如何让B :: Deparse在核心转储上运行?或者,或者,如何从核心重新启动程序,加载B :: Deparse并执行它?

欢迎任何想法.



1> Josh Jore..:

ysth让我在IRC上评论你的问题.我已经完成了一堆"反汇编"编译的perl和东西(只看我的CPAN页面[ http://search.cpan.org/~jjore]).

Perl将你的源代码编译成一个结构树OP*,偶尔会有一个C指针,SV*它们是perl值.你的核心转储现在有很多这些OP*并存储起来SV*.

最好的世界将是像B :: Deparse这样的perl模块 为您做信息理解工作.它的工作原理是使用一个轻型接口来记录B::OPB::SV类中的perl内存(记录在B,perlguts和 perlhack中).这对你来说是不现实的,因为B::*对象只是一个指向内存的指针,带有访问器来解码结构供我们使用.考虑:

require Data::Dumper;
require Scalar::Util;
require B;

my $value = 'this is a string';

my $sv      = B::svref_2object( \ $value );
my $address = Scalar::Util::refaddr( \ $value );

local $Data::Dumper::Sortkeys = 1;
local $Data::Dumper::Purity   = 1;
print Data::Dumper::Dumper(
  {
    address => $address,
    value   => \ $value,
    sv      => $sv,
    sv_attr => {
      CUR           => $sv->CUR,
      LEN           => $sv->LEN,
      PV            => $sv->PV,
      PVBM          => $sv->PVBM,
      PVX           => $sv->PVX,
      as_string     => $sv->as_string,
      FLAGS         => $sv->FLAGS,
      MAGICAL       => $sv->MAGICAL,
      POK           => $sv->POK,
      REFCNT        => $sv->REFCNT,
      ROK           => $sv->ROK,
      SvTYPE        => $sv->SvTYPE,
      object_2svref => $sv->object_2svref,
    },
  }
);

运行时显示B::PV对象(它是ISA B::SV)实际上只是编译字符串的内存表示的接口this is a string.

$VAR1 = {
          'address' => 438506984,
          'sv' => bless( do{\(my $o = 438506984)}, 'B::PV' ),
          'sv_attr' => {
                         'CUR' => 16,
                         'FLAGS' => 279557,
                         'LEN' => 24,
                         'MAGICAL' => 0,
                         'POK' => 1024,
                         'PV' => 'this is a string',
                         'PVBM' => 'this is a string',
                         'PVX' => 'this is a string',
                         'REFCNT' => 2,
                         'ROK' => 0,
                         'SvTYPE' => 5,
                         'as_string' => 'this is a string',
                         'object_2svref' => \'this is a string'
                       },
          'value' => do{my $o}
        };
$VAR1->{'value'} = $VAR1->{'sv_attr'}{'object_2svref'};

然而,这意味着任何B::*使用代码必须实际上在实时内存上运行.Tye McQueen认为他记得一个C调试器,它可以完全恢复给定核心转储的工作过程.我gdb 不能.gdb可以允许您转储OP*SV*结构的内容.您很可能只是阅读转储的结构来解释程序的结构.如果你愿意的话,你可以使用 gdb转储结构,然后合成地创建B::*在接口中表现的对象,就好像它们是普通的并B::Deparse在其上使用一样 .从根本上说,我们的deparser和其他调试转储工具大多是面向对象的,所以你可以通过创建一堆伪B::*类和对象来"欺骗"它们.

您可能会发现阅读B :: Deparse类的coderef2text方法具有指导意义.它接受函数引用,将其强制转换为B::CV 对象,并将其用于deparse_sub方法的输入:

require B;
require B::Deparse;
sub your_function { ... }

my $cv = B::svref_2object( \ &your_function );
my $deparser = B::Deparse->new;
print $deparser->deparse_sub( $cv );

有关更温和的介绍OP*和相关的想法,请参阅更新的 PerlGuts Illustrated和Optree内容.

推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有