Filter::decrypt#

📦 std

A sample decrypting source filter: the source after use Filter::decrypt is XOR-ed with “Perl” as the compiler reads it.

Synopsis#

use Filter::decrypt;

The rest of the file is the output of the dist’s decrypt/encrypt script: the two bytes 0xff 0x00, then the source, each block of four bytes XOR-ed with “Perl”.

How it works#

import installs a source filter. On its first read it checks the two-byte header (“truncated file”, “bad encryption format”) and that no filter was added on the use line after it (“too many filters”); then it reads four bytes at a time and serves the decrypted text by the line or the block, as the compiler asks. import dies “debugger disabled” under perl -d, and loading the module dies “Aborting, Compiler detected” once the compiler backend (B) is loaded.

The module is a template for a real decryption filter, not a protection: the decrypted source passes through memory, and B::Deparse can print what it compiled to.

This is a native implementation of decrypt.xs of Filter 1.65 as the dist builds it (-DBYPASS: no refusal of a dynamically linked module or of a perl built with -DDEBUGGING); its Filter/decrypt.pm is used unchanged.

Differences from upstream#

One, where perl 5.44 with decrypt.xs crashes (t/81-xs-native/Filter/150-or-better.t):

  • Filter::decrypt->import while nothing is being compiled installs nothing and leaves memory alone. decrypt.xs stores the filter’s state in the slots of a handle the tokenizer never made, past the end of the string it allocated: it overwrites neighbouring variables, and perl5 can segfault.