How to open and edit encrypted perl script? - perl

I have a perl script that is encrypted. This script can be compiled only if Filter::decrypt is installed. I have that Filter and I installed it and the script is compiled with no problem, but now I want to open that script with some text editor and edit it.
Can someone help me and tell me how can I do this?

Pretty fundamentally - it's extremely difficult to make a script unreadable, simply because perl is an interpreted language. Exactly how to disentangle something is more a question of how it got tangled in the first place.
So I would suggest as a first port of call - have a look through Mastering Perl which has a whole chapter on the subject of disassembling perl code.
However if you just look at the Filter::decrypt module page, it indicates several places which the module simply cannot cover - you can only truly 'protect' code if you've control of the perl interpreter in the first place. However the things it suggests are:
Strip the Perl binary to remove all symbols.
Build the decrypt extension using static linking. If the extension is provided as a dynamic module, there is nothing to stop someone from linking it at run time with a modified Perl binary.
Do not build Perl with -DDEBUGGING. If you do then your source can be retrieved with the -Dp command line option.
The sample filter contains logic to detect the DEBUGGING option.
Do not build Perl with C debugging support enabled.
Do not implement the decryption filter as a sub-process (like the cpp source filter). It is possible to peek into the pipe that connects to the sub-process.
Check that the Perl Compiler isn't being used.
There is code in the BOOT: section of decrypt.xs that shows how to detect the presence of the Compiler. Make sure you include it in your module.
Assuming you haven't taken any steps to spot when the compiler is in use and you have an encrypted Perl script called "myscript.pl", you can get access the source code inside it using the perl Compiler backend, like this
perl -MO=Deparse myscript.pl
Note that even if you have included the BOOT: test, it is still possible to use the Deparse module to get the source code for individual subroutines.
So:
perl -MO=Deparse yourscript
perl -Dp yourscript
If these don't work - look at your local copy of Filter::decrypt and alter it so it prints the decrypted result.

Best option: Just edit your unencrypted copy and reinstall it.
Alternative: Use decr (comes with Filter::decrypt) to decrypt an encrypted file.

Related

Can I suppress the "Perl API version %s of %s does not match %s" error

I copied a Perl module (DBD::Pg) from one system to another to run some quick checks on a Mojolicious project. On the new system, it all works fine when I run it under morbo (the Mojolicious test web daemon). But when I try to run the tests (via the Module::Build installer), I get the error:
Perl API version v5.16.0 of DBD::Pg does not match v5.20.0 at /usr/local/lib/perl/DynaLoader.pm line 216.
I researched why I am getting this, and read the explanation in the perldoc. But since the project runs under morbo, that seems to imply to me that the version mismatch may be trivial in this case. It looks like PerlXS does make some allowances for disabling VERSIONCHECK, but I don't see how that can be applied when running a Perl script.
You can't copy non-pure Perl modules from one system to the next (or into one group of perl lib directories into another perl's). Generally the code in those modules is compiled against the specific perl binary. That binary could have linked to different libraries, changed how it does things, used a different compiler, and many other things. It may not even work if the perl versions are the same.
Instead, install the DBD::Pg for each perl that needs to use it.

Replace default perl on Ubuntu 16.04

I got a huge project written on Perl, which contains many of scripts which starts with typical #!/usr/bin/perl
For this project I need a custom-built Perl to be compiled from source.
I tried just to replace /usr/bin/perl with my compiled one but OS becomes broken (for ex. module version mismatch etc).
So is there any correct way to replace system perl with my own-built one or the easiest way would be to edit all tons of scripts and replace /usr/bin/perl with /usr/local/bin/perl or something like this?
Do not replace system perl (or system binaries in general). You can build it to another location (as you suggested, /usr/local for example) and call it manually.
My personal preference is to use plenv. There's a nice guide here to get you started.
If you admin the server and other users are logging in an using your scripts, you'll want to build plenv somewhere outside your home directory (eg. /opt/plenv) and ensure that all users $PATH is prepended with the bin path of your new perl. Without digressing too much, this can be done in /etc/profile or even better to declare you custom profile mods in a custom profile script (eg. /etc/profile.d/custom.sh).
I would also suggest using a more portable shebang such as #!/usr/bin/env perl which will use whichever perl is in a users $PATH first. The only exception to this is cron jobs, which I typically always hardcode full paths. (This is a personal preference based entirely how I admin my boxes and probably not a good idea to recommend unless you know the full repercussions. Administering a server is entirely subjective based on it's use-case, your use-case likely differs vastly from mine).
According to comments, there is no solution to replace system Perl without of destroying something but the're 3 solutions to solve the descibed problem. For all of them i need to modify all the scripts.
Using #!/usr/bin/env perl (need to be very careful and place custom perl bin path before all at $PATH of user which runs the script. The nice solution would be to set PATH exactly at crontab.
Using straight new perl path at shebang like as #!/usr/local/bin/perl5.26.1
Totally remove shebang from scripts and use plain calls at cron and manual runs - like as /usr/bin/perl script.pl. Or just use plain calls - shebang would be ignored.
Special thanks to #Joshua and #ikegami

postgresql autodoc

I want to generate a ER Diagram sort of, of my spatial database i created inside of Postgresql. As i am also new to Postgresql, i am not too sure if the diagramming functionality can be done using whats offered by the PgAdmin (not referring to the Graphical Query Builder). However, it seems to me there is none. I read around that there is a perl based tool called postgresql_autodoc that can run through PostgreSQL system tables and return HTML, Dot, Dia and DocBook XML which describes the database. Now this is not exactly what i wanted but its the closest option i have. So i have successfully installed, ActivePerl 5.8 and DBD-Pg 2.10.0 for Perl 5.8 (DBD PG is a Perl DBI driver for the PostgreSQL database) and i have also downloaded the postgresql_autodoc.pl file. I have also added the path for Perl. But when i try to run the postgresql_autodoc.pl via the command prompt, i was getting this error: Possible Unintended Interpolation of #TEMPLATE in string at C:/Perl/bin/postgresql_autodoc.pl line 1831. Global symbol "#TEMPLATE" requires explicit package name at C:/Perl/bin/postgresql_autodoc.pl line 1831. Execution of C:/Perl/bin/postgresql_autodoc.pl aborted due to compilation errors.
I tried to view the postgresql_autodoc.pl using notepad++ however i have no experience with the perl language and so i cant figure out what is really wrong. All i could do is locate line 1831 but i dont know what i should do to fix this problem.
The postgresql_autodoc.pl file was downloaded from: http://www.rbt.ca/autodoc/
I would appreciate if anyone can help me here!
Thanks in advance
Barbara
That thingy, ##TEMPLATE-DIR##, is a string that is replaced when you build and install the module -- meaning you're not supposed to run it directly from the unpacked archive.
Most Perl modules are installed with a more or less simple three-step installation process, something like perl Makefile.PL ; make ; make install. However, this package is slightly different, you seem only to need make install.
Note that I have no experience with installing Perl modules on Windows with ActiveState. So the above may not work (e.g. if there's no make utility which is usually not part of Perl -- though it might be part of the ActiveState Perl distribution).
But there's a workaround. You can simply do what the install script does and replace the ##TEMPLATE-DIR## string yourself. It can be done easily with any text editor by replacing the two occurrences of ##TEMPLATE-DIR## with the path to where the postgresql_autodoc.pl script has been unpacked to -- meaning it's the path the script will look for the *.tmpl files in.
Note that Windows path names can be written with forward slashes in Perl, meaning C:/Temp/postgresql_autodoc should be OK.

Is there ever a reason to include the shebang line in Perl packages?

I realize that I should include the shebang line only in scripts we want to run directly in the shell. I also do not see the shebang line included in any of the big module packages I have installed locally.
However, I was still curious if people might include it for some other reason I'm not yet aware of. Or if there perhaps might be something like a (e.g.) ~'historical' reason for including it. Or should the shebang line never ever be included in .pm files(period) for fear of my house exploding?
No. A shebang marks a file as executable, and a module is usually not executable.
In general, there are exceptions. Python has an idiom to detect whether the current file is the one invoked by the interpreter, and quite some modules use this to run their unit tests when invoked standalone. This is not common in the Perl community, where you have extra unit test files bundled with the module on CPAN.
So even with this possible exception in mind, I would not consider it good style to include a shebang in a module file which is not meant to be executed directly.
The short answer is NO, but there is no right or wrong answer.
The purpose of the shebang is to let the OS know where the interpreter is. There is no requirement to add it to any Perl file (script or module). And under Windows it is ignored anyway**.
More specifically, in most cases there is no reason to add it to a module, unless there is some reason why you would want to execute that module directly. A Perl module is really just a Perl script anyway, with a 'package' command at the top.
Either way, it won't hurt if it is there, but in most cases it doesn't make sense.
** Regardless of how Perl is started it will always look at the shebang for command line switches. This even goes for Windows, where the OS doesn't look for the shebang line, but when Perl scans the file it will. See http://perldoc.perl.org/perlrun.html.

Perl to generate one executable file for a script which uses any number of modules and libraries

I am working on creating an agent in perl which does several actions. It uses several modules which are in .pm format and also few libraries. Now i want to convert it as one executable file so that i can install in n number of servers by copying that single file. Is it something i can achieve in perl? I am just a beginner in perl, perhaps my question might sound dumb but it will teach me something.
pp script provided with PAR::Packer is able to create single-file executables. An example from its page:
pp -o foo foo.pl bar.pl # Pack 'foo.pl' and 'bar.pl' into 'foo'
Some modules are included with Perl, so even though they're separate modules, they will work on other Perl installs without installing those modules. These include File::Copy, File::Find, Time::Piece.
You can see the listing of all standard modules on the Perldoc home page. Be sure to set the drop down version field (located on the left side) to the version that you're using. It goes all the way back to Perl 5.8.8 which is on Solaris.
It is entirely possible that the modules you need are already included in the standard Perl distribution, so there's no need to worry. Sometimes, you can substitute a non-standard module that's being used for one that's a standard module with little rewriting.
Some modules include compiled C code and can't be redistributed. They must be compiled on the machine they'r running on and installed. However, most modules are pure Perl modules, and can be redistributed with a program.
If a module isn't a standard module, and it's a pure Perl module, there are two ways it can be redistributed:
Perl has an #INC list that says what directories to search for when you search for modules. There's a Perl use lib pragma that allows you to add directories. You could include modules as sub directories for your program, and then zip up the entire structure. Users would unzip the entire directory tree which would include your program and the modules you need. By the way, the default #INC usually includes the current directory.
The other way is to append the modules to your program and then remove the use statement for that module (since it's now part of the file). This is a bit tricky, but it means a single program file.
Just remember that a module might require another module, so check thoroughly.
Another thing you can do is check for the module, and if it isn't there, download it via CPAN. Testing is easy:
BEGIN {
eval {
require My::Module; Module->import( LIST );
};
if ($#) {
die qq(Module doesn't exist);
}
}
Of course, doing a die is sort of silly because use would do that. However, it might be possible instead of dying to load the module via the CPAN module programmer's interface. I've never done that, and I don't know people who have. But, it is possible.
So, your best bet is to check to see if your program uses standard Perl modules, and if not, see if you can modify the program to use them. For example, if your program uses Archive::Zip, you might be able to modify it to use IO::Uncompress::Unzip and IO::Compress::Zip instead.
Otherwise, your choice is to try include those modules for installation (and watch for recursiveness and non-Pure Perl modules) or to try to detect that a module isn't installed, and programmatically install it.
The answer is a bit complicated.
The nature of Perl makes it practically impossible to compile a perl script in most use cases, so that a single executable could be distributed (with executable in the Windows sense). There are ways to do something similar, but sadly I don't know them.
But you can actually embed the Perl interpreter inside any C application, including the Perl source (your scripts + modules). When you statically link all C libraries, this should work as well. You can then use the Perl API to call your scripts.
If all of the servers you target are guaranteed to run the exact same OS, using the exact same libraries, and are preferably a *nix of some sort, it would be possible to pack all required files into an archive and write an install script. It is possible to write self-extracting shell scripts that contain the archive they are about to unpack. Same goes with perl, using the special __DATA__ command and the DATA filehandle:
#!/usr/bin/perl
print for <DATA>;
__DATA__
1
2
3
prints
1
2
3
Works great for piping data to tar as well.
You should include all dependent modules and all compiled libraries into the file and figure out a metadata system to install all files to the correct place.
As a general rule, software should rather be compiled on the target system itself, than just copying the binary files. It is too easy to overlook architecture differencies, configuration files or special registration entries hidden from view.
If you have to target different systems, it might be better to write a script that delegates the bulk of the installation to cpan or whatever perl package manager you prefer. This will be more flexible than hard-coding filepaths.
#!/bin/bash
cpan install Foo::Bar
cpan install Acme
cpan install ...
# etc.
I would stick with that.
The most elegant solution would be to create your own package or distribution like the ones you download from CPAN. As you would include a metadata file referencing all your dependencies, cpan would figure out everything by itself and do possibly neccessary compilation. I don't think this exactly is a beginners topic, but it would give you max flexibility and maintainability (easy upgrades!). This should make it fairly easy to include some installation tests.
This is just for starters, I am sure the internet or somebody else with more knowledge will elaborate.