混淆难题:你能弄清楚这个 Perl 函数的作用吗?

发布于 2024-07-05 19:56:15 字数 288 浏览 10 评论 0原文

sub foo {[$#{$_[!$||$|]}*@{$_[!!$_^!$_]}?@{$_[!$..!!$.]}[$_[@--@+]%
@{$_[$==~/(?=)//!$`]}..$#{$_[$??!!$?:!$?]},($)?!$):!!$))..$_[$--$-]%@{
$_[$]/$]]}-(!!$++!$+)]:@{$_[!!$^^^!$^^]}]}

更新:我认为“谜题”这个词暗示着这一点,但是:知道它的作用 - 我写了它。 如果您对这个谜题不感兴趣,请不要在上面浪费时间。

sub foo {[$#{$_[!$||$|]}*@{$_[!!$_^!$_]}?@{$_[!$..!!$.]}[$_[@--@+]%
@{$_[$==~/(?=)//!]}..$#{$_[$??!!$?:!$?]},($)?!$):!!$))..$_[$--$-]%@{
$_[$]/$]]}-(!!$++!$+)]:@{$_[!!$^^^!$^^]}]}

update: I thought the word "puzzle" would imply this, but: I know what it does - I wrote it. If the puzzle doesn't interest you, please don't waste any time on it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

许久 2024-07-12 19:56:15

以下是如何弄清楚如何对该子例程进行反混淆的方法。

抱歉太长了

首先让我们整理一下代码,并添加有用的注释。

sub foo {
  [
    (
      # ($#{$_[1]})
      $#{
        $_[
          ! ( $| | $| )
          # $OUTPUT_AUTOFLUSH === $|
          # $| is usually 0
          # ! ( $| | $| )
          # ! (  0 |  0 )
          # ! (  0 )
          # 1
        ]
      }

      *

      # @{$_[1]}
      @{
        $_[
          !!$_ ^ !$_

          # !! 1 ^ ! 1
          # !  0 ^   0
          #    1 ^   0
          # 1

          # !! 0 ^ ! 0
          # !  1 ^   1
          #    0 ^   1
          # 1
        ]
      }
    )

    ?


    # @{$_[1]}
    @{
      $_[
        !$. . !!$.
        # $INPUT_LINE_NUMBER === $.
        # $. starts at 1
        # !$. . !!$.
        # ! 1 . !! 1
        #   0 . ! 0
        #   0 . 1
        #   01
      ]
    }

    [
      # $_[0]
      $_[
        # @LAST_MATCH_START - @LAST_MATCH_END
        # 0
        @- - @+
      ]

      %


      # @{$_[1]}
      @{
        $_[
          $= =~ /(?=)/ / !

以下是如何弄清楚如何对该子例程进行反混淆的方法。

抱歉太长了

首先让我们整理一下代码,并添加有用的注释。

#( fix highlighting )`/ # $= is usually 60 # /(?=)/ will match, returns 1 #

以下是如何弄清楚如何对该子例程进行反混淆的方法。

抱歉太长了

首先让我们整理一下代码,并添加有用的注释。

will be '' # 1 / ! '' # 1 / ! 0 # 1 / 1 # 1 ] } .. # $#{$_[1]} $#{ $_[ $? ? !!$? : !$? # $CHILD_ERROR === $? # $? ? !!$? : !$? # 0 ? !! 0 : ! 0 # 0 ? 0 : 1 # 1 # 1 ? !! 1 : ! 1 # 1 ? 1 : 0 # 1 ] } , # ( 0 ) ( $) ? !$) : !!$) # $EFFECTIVE_GROUP_ID === $) # $) ? !$) : !!$) # 0 ? ! 0 : !! 0 # 0 ? 1 : 0 # 0 # 1 ? ! 1 : !! 1 # 1 ? 0 : 1 # 0 ) .. # $_[0] $_[ $- - $- # 0 # $LAST_PAREN_MATCH = $- # 1 - 1 == 0 # 5 - 5 == 0 ] % # @{$_[1]} @{ $_[ $] / $] # $] === The version + patchlevel / 1000 of the Perl interpreter. # 1 / 1 == 1 # 5 / 5 == 1 ] } - # ( 1 ) ( !!$+ + !$+ # !! 1 + ! 1 # ! 0 + 0 # 1 + 0 # 1 ) ] : # @{$_[1]} @{ $_[ !!$^^ ^ !$^^ # !! 1 ^ ! 1 # ! 0 ^ 0 # 1 ^ 0 # 1 # !! 0 ^ ! 0 # ! 1 ^ 1 # 0 ^ 1 # 1 ] } ] }

现在让我们删除一些混淆。

sub foo{
  [
    (
      $#{$_[1]} * @{$_[1]}
    )

    ?

    @{$_[1]}[
      ( $_[0] % @{$_[1]} ) .. $#{$_[1]}

      ,

      0 .. ( $_[0] % @{$_[1]} - 1 )
    ]

    :

    @{$_[1]}
  ]
}

现在我们已经了解了正在发生的事情,让我们命名变量。

sub foo{
  my( $item_0, $arr_1 ) = @_;
  my $len_1  = @$arr_1;

  [
      # This essentially just checks that the length of $arr_1 is greater than 1
      ( ( $len_1 -1 ) * $len_1 )
      # ( ( $len_1 -1 ) * $len_1 )
      # ( (      5 -1 ) *      5 )
      #             4   *      5
      # 20
      # 20 ? 1 : 0 == 1

      # ( ( $len_1 -1 ) * $len_1 )
      # ( (      2 -1 ) *      2 )
      #             1   *      2
      # 2
      # 2 ? 1 : 0 == 1

      # ( ( $len_1 -1 ) * $len_1 )
      # ( (      1 -1 ) *      1 )
      #             0   *      1
      # 0
      # 0 ? 1 : 0 == 0

      # ( ( $len_1 -1 ) * $len_1 )
      # ( (      0 -1 ) *      0 )
      #            -1   *      0
      # 0
      # 0 ? 1 : 0 == 0

    ?

      @{$arr_1}[
        ( $item_0 % $len_1 ) .. ( $len_1 -1 ),
        0 .. ( $item_0 % $len_1 - 1 )
      ]

    :

      # If we get here, @$arr_1 is either empty or has only one element
      @$arr_1
  ]
}

让我们重构代码以使其更具可读性。

sub foo{
  my( $item_0, $arr_1 ) = @_;
  my $len_1  = @$arr_1;

  if( $len_1 > 1 ){
    return [
      @{$arr_1}[
        ( $item_0 % $len_1 ) .. ( $len_1 -1 ),
        0 .. ( $item_0 % $len_1 - 1 )
      ]
    ];
  }elsif( $len_1 ){
    return [ @$arr_1 ];
  }else{
    return [];
  }
}

Here is how you figure out how to de-obfuscate this subroutine.

Sorry for the length

First let's tidy up the code, and add useful comments.

sub foo {
  [
    (
      # ($#{$_[1]})
      $#{
        $_[
          ! ( $| | $| )
          # $OUTPUT_AUTOFLUSH === $|
          # $| is usually 0
          # ! ( $| | $| )
          # ! (  0 |  0 )
          # ! (  0 )
          # 1
        ]
      }

      *

      # @{$_[1]}
      @{
        $_[
          !!$_ ^ !$_

          # !! 1 ^ ! 1
          # !  0 ^   0
          #    1 ^   0
          # 1

          # !! 0 ^ ! 0
          # !  1 ^   1
          #    0 ^   1
          # 1
        ]
      }
    )

    ?


    # @{$_[1]}
    @{
      $_[
        !$. . !!$.
        # $INPUT_LINE_NUMBER === $.
        # $. starts at 1
        # !$. . !!$.
        # ! 1 . !! 1
        #   0 . ! 0
        #   0 . 1
        #   01
      ]
    }

    [
      # $_[0]
      $_[
        # @LAST_MATCH_START - @LAST_MATCH_END
        # 0
        @- - @+
      ]

      %


      # @{$_[1]}
      @{
        $_[
          $= =~ /(?=)/ / !

Here is how you figure out how to de-obfuscate this subroutine.

Sorry for the length

First let's tidy up the code, and add useful comments.

#( fix highlighting )`/ # $= is usually 60 # /(?=)/ will match, returns 1 #

Here is how you figure out how to de-obfuscate this subroutine.

Sorry for the length

First let's tidy up the code, and add useful comments.

will be '' # 1 / ! '' # 1 / ! 0 # 1 / 1 # 1 ] } .. # $#{$_[1]} $#{ $_[ $? ? !!$? : !$? # $CHILD_ERROR === $? # $? ? !!$? : !$? # 0 ? !! 0 : ! 0 # 0 ? 0 : 1 # 1 # 1 ? !! 1 : ! 1 # 1 ? 1 : 0 # 1 ] } , # ( 0 ) ( $) ? !$) : !!$) # $EFFECTIVE_GROUP_ID === $) # $) ? !$) : !!$) # 0 ? ! 0 : !! 0 # 0 ? 1 : 0 # 0 # 1 ? ! 1 : !! 1 # 1 ? 0 : 1 # 0 ) .. # $_[0] $_[ $- - $- # 0 # $LAST_PAREN_MATCH = $- # 1 - 1 == 0 # 5 - 5 == 0 ] % # @{$_[1]} @{ $_[ $] / $] # $] === The version + patchlevel / 1000 of the Perl interpreter. # 1 / 1 == 1 # 5 / 5 == 1 ] } - # ( 1 ) ( !!$+ + !$+ # !! 1 + ! 1 # ! 0 + 0 # 1 + 0 # 1 ) ] : # @{$_[1]} @{ $_[ !!$^^ ^ !$^^ # !! 1 ^ ! 1 # ! 0 ^ 0 # 1 ^ 0 # 1 # !! 0 ^ ! 0 # ! 1 ^ 1 # 0 ^ 1 # 1 ] } ] }

Now let's remove some of the obfuscation.

sub foo{
  [
    (
      $#{$_[1]} * @{$_[1]}
    )

    ?

    @{$_[1]}[
      ( $_[0] % @{$_[1]} ) .. $#{$_[1]}

      ,

      0 .. ( $_[0] % @{$_[1]} - 1 )
    ]

    :

    @{$_[1]}
  ]
}

Now that we have some idea of what is going on, let's name the variables.

sub foo{
  my( $item_0, $arr_1 ) = @_;
  my $len_1  = @$arr_1;

  [
      # This essentially just checks that the length of $arr_1 is greater than 1
      ( ( $len_1 -1 ) * $len_1 )
      # ( ( $len_1 -1 ) * $len_1 )
      # ( (      5 -1 ) *      5 )
      #             4   *      5
      # 20
      # 20 ? 1 : 0 == 1

      # ( ( $len_1 -1 ) * $len_1 )
      # ( (      2 -1 ) *      2 )
      #             1   *      2
      # 2
      # 2 ? 1 : 0 == 1

      # ( ( $len_1 -1 ) * $len_1 )
      # ( (      1 -1 ) *      1 )
      #             0   *      1
      # 0
      # 0 ? 1 : 0 == 0

      # ( ( $len_1 -1 ) * $len_1 )
      # ( (      0 -1 ) *      0 )
      #            -1   *      0
      # 0
      # 0 ? 1 : 0 == 0

    ?

      @{$arr_1}[
        ( $item_0 % $len_1 ) .. ( $len_1 -1 ),
        0 .. ( $item_0 % $len_1 - 1 )
      ]

    :

      # If we get here, @$arr_1 is either empty or has only one element
      @$arr_1
  ]
}

Let's refactor the code to make it a little bit more readable.

sub foo{
  my( $item_0, $arr_1 ) = @_;
  my $len_1  = @$arr_1;

  if( $len_1 > 1 ){
    return [
      @{$arr_1}[
        ( $item_0 % $len_1 ) .. ( $len_1 -1 ),
        0 .. ( $item_0 % $len_1 - 1 )
      ]
    ];
  }elsif( $len_1 ){
    return [ @$arr_1 ];
  }else{
    return [];
  }
}
凉栀 2024-07-12 19:56:15

在处理我的其他答案时,我发现这个命令很有帮助。

perl -MO=Concise,foo,-terse,-compact obpuz.pl > obpuz.out

B: :简洁

I found this command helpful, when working on my other answer.

perl -MO=Concise,foo,-terse,-compact obpuz.pl > obpuz.out

B::Concise

你是我的挚爱i 2024-07-12 19:56:15

它接受两个 arrayref 并返回一个新的 arrayref,其中第二个数组的内容经过重新排列,使得第二部分位于第一部分之前,并根据第一个数组的内存位置在某个点进行分割。 当第二个数组为空或包含一项时,仅返回第二个数组的副本。 等价于以下内容:

sub foo {
    my ($list1, $list2) = @_;
    my @output;
    if (@$list2 > 0) {
        my $split = $list1 % @$list2;
        @output = @$list2[$split .. $#$list2, 0 .. ($split - 1)];
    } else {
        @output = @$list2;
    }
    return \@output;
}

$list1 % @$list2 本质上是根据 $list 选择一个随机位置来分割数组,在计算时该位置计算为 $list 的内存地址在数字上下文中。

原文大多使用大量涉及标点变量的同义反复来进行混淆。 例如

  • <代码>!$| | $| 始终为 1
  • @- - @+ 始终为 0

已更新,请注意 perltidy 在这里的破译非常有帮助,但它被 噎住了! !$^^^!$^^,将其重新格式化为 !!$^ ^ ^ !$^ ^,这是无效的 Perl; 它应该是 !!$^^ ^ !$^^。 这可能是 RWendi 编译错误的原因。

It takes two arrayrefs and returns a new arrayref with the contents of the second array rearranged such that the second part comes before the first part, split at a point based on the memory location of the first array. When the second array is empty or contains one item, just returns a copy of the second array. Equivalent to the following:

sub foo {
    my ($list1, $list2) = @_;
    my @output;
    if (@$list2 > 0) {
        my $split = $list1 % @$list2;
        @output = @$list2[$split .. $#$list2, 0 .. ($split - 1)];
    } else {
        @output = @$list2;
    }
    return \@output;
}

$list1 % @$list2 essentially picks a random place to split the array, based on $list which evaluates to the memory address of $list when evaluated in a numeric context.

The original mostly uses a lot of tautologies involving punctuation variables to obfuscate. e.g.

  • !$| | $| is always 1
  • @- - @+ is always 0

Updated to note that perltidy was very helpful deciphering here, but it choked on !!$^^^!$^^, which it reformats to !!$^ ^ ^ !$^ ^, which is invalid Perl; it should be !!$^^ ^ !$^^. This might be the cause of RWendi's compile error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文