dynamic code generation in perl
DESCRIPTION
Dynamically change the code that your application is using.TRANSCRIPT
Dynamic Code Generation
Marian HackMan Marinov
22.Nov.2014
Marian HackMan Marinov Dynamic Code Generation
Why would you need that?
Marian HackMan Marinov Dynamic Code Generation
Why would you need that?
Faster Development time
Marian HackMan Marinov Dynamic Code Generation
Why would you need that?
Faster Development time
Easier interfaces
Marian HackMan Marinov Dynamic Code Generation
Why would you need that?
Faster Development time
Easier interfaces
Abstraction
Marian HackMan Marinov Dynamic Code Generation
Why would you need that?
Faster Development time
Easier interfaces
Abstraction
Obfuscation
Marian HackMan Marinov Dynamic Code Generation
Why would you need that?
Faster Development time
Easier interfaces
Abstraction
Obfuscation/crypto
Performance
Marian HackMan Marinov Dynamic Code Generation
I will focus mainly on PERFORMANCE
Marian HackMan Marinov Dynamic Code Generation
Let’s start with a basic script
#!/usr/bin/perl
use warnings;
use strict;
sub DEBUG { 0; };
use constant ADEBUG => 0;
Marian HackMan Marinov Dynamic Code Generation
The following would be optimised out
if (DEBUG) {
print "Debuging\n";
}
if (ADEBUG) {
print "Debuging A\n";
}
Marian HackMan Marinov Dynamic Code Generation
What if we need to have something like this
if (defined($ARGV[0]) && $ARGV[0] eq ’ok’) {
sub DEBUG { 1; };
}
Marian HackMan Marinov Dynamic Code Generation
What if we need to have something like this
if (defined($ARGV[0]) && $ARGV[0] eq ’ok’) {
sub DEBUG { 1; };
}
$ perl f.pl ok
Subroutine DEBUG redefined at f.pl line 9.
$
Marian HackMan Marinov Dynamic Code Generation
Or something like this
if (defined($ARGV[0]) && $ARGV[0] eq ’ok’) {
ADEBUG => 1;
}
Marian HackMan Marinov Dynamic Code Generation
Or something like this
if (defined($ARGV[0]) && $ARGV[0] eq ’ok’) {
ADEBUG => 1;
}
$ perl f.pl ok
Useless use of a constant ("ADEBUG") in void context at f.pl line 9.
Marian HackMan Marinov Dynamic Code Generation
What if we start playing dirty :)
if (defined($ARGV[0]) && $ARGV[0] eq ’ok’) {
undef &ADEBUG;
use constant ADEBUG => 1;
}
$ perl f.pl ok
Constant subroutine main::ADEBUG redefined at /usr/share/perl5/constant.pm line 140.
Constant subroutine (anonymous) undefined at f.pl line 9.
Debuging
$
Marian HackMan Marinov Dynamic Code Generation
Let’s declare this as futile
Figure : Resistance is futile
Marian HackMan Marinov Dynamic Code Generation
So why did I tried to redifine a constant ?
What if we have a script which does:
while (my $line = <$fd>) {
if ($line =~ /RE/) { };
if ($line =~ /RE/) { };
....
....
if ($line =~ /RE/) { };
}
Marian HackMan Marinov Dynamic Code Generation
So why did I tried to redifine a constant ?
We can update it to:
while (my $line = <$fd>) {
if ($config{’type1’} && $line =~ /RE/) { };
if ($config{’type2’} && $line =~ /RE/) { };
....
....
if ($config{’typeN’} && $line =~ /RE/) { };
}
Marian HackMan Marinov Dynamic Code Generation
Hook::Filter
First looked at this
use Hook::Filter::RulePool qw(get_rule_pool);
get_rule_pool->add_rule("subname eq ’mydebug’ &&
from =~ /^My::Filthy::Attempt/");
->add_rule("from =~ /^My::Filthy::Attempt::func$/");
->add_rule("args(1) =~ /bob/");
Marian HackMan Marinov Dynamic Code Generation
Welcome to perlfilter
Preprocessor like directives for Perl
Marian HackMan Marinov Dynamic Code Generation
perlfilter
Filter::Util::Call - the main filter module
Marian HackMan Marinov Dynamic Code Generation
perlfilter
Filter::Util::Call - the main filter module
Filter::Simple - simplified version of the Util::Call
Marian HackMan Marinov Dynamic Code Generation
perlfilter
Filter::Util::Call - the main filter module
Filter::Simple - simplified version of the Util::Call
Filter::sh - filter the source trough cmd with shell
Marian HackMan Marinov Dynamic Code Generation
perlfilter
Filter::Util::Call - the main filter module
Filter::Simple - simplified version of the Util::Call
Filter::sh - filter the source trough cmd with shell
Filter::exec - filter the source trough cmd
Marian HackMan Marinov Dynamic Code Generation
perlfilter
Filter::Util::Call - the main filter module
Filter::Simple - simplified version of the Util::Call
Filter::sh - filter the source trough cmd with shell
Filter::exec - filter the source trough cmd
Filter::tee - copies all text from the line after the use
Marian HackMan Marinov Dynamic Code Generation
perlfilter
Filter::Util::Call - the main filter module
Filter::Simple - simplified version of the Util::Call
Filter::sh - filter the source trough cmd with shell
Filter::exec - filter the source trough cmd
Filter::tee - copies all text from the line after the use
Filter::cpp - pipes all souce trough the cpp pre-processor
Marian HackMan Marinov Dynamic Code Generation
Crypto filters
Filter::decrypt - example documentation for enc/decrypting
Marian HackMan Marinov Dynamic Code Generation
Crypto filters
Filter::decrypt - example documentation for enc/decrypting
Filter::Rijndael - decrypting source filter based on Rijndaelencryption
Marian HackMan Marinov Dynamic Code Generation
Crypto filters
Filter::decrypt - example documentation for enc/decrypting
Filter::Rijndael - decrypting source filter based on Rijndaelencryption
Filter::CBC - Source filter for Cipher Block Chaining
Marian HackMan Marinov Dynamic Code Generation
Crypto filters
Filter::decrypt - example documentation for enc/decrypting
Filter::Rijndael - decrypting source filter based on Rijndaelencryption
Filter::CBC - Source filter for Cipher Block Chaining
Filter::Crypto::CryptFile & Filter::Crypto::Decrypt
Marian HackMan Marinov Dynamic Code Generation
Filter::Util::Call part I
package Debug;
use strict;
use warnings;
use Filter::Util::Call;
use constant TRUE => 1;
use constant FALSE => 0;
sub import {
my ($type) = @_;
my (%context) = (
Enabled => defined $ENV{DEBUG},
InTraceBlock => FALSE,
Filename => (caller)[1],
LineNo => 0,
LastBegin => 0,
);
filter_add(bless \%context);
}Marian HackMan Marinov Dynamic Code Generation
Filter::Util::Call part II
sub filter {
my ($self) = @_;
my ($status);
$status = filter_read();
++ $self->{LineNo};
if ($self->{InTraceBlock}) {
if (/^\s*##\s*DEBUG_END/) {
$self->{InTraceBlock} = FALSE;
}
s/^/#/ if ! $self->{Enabled};
} elsif ( /^\s*##\s*DEBUG_BEGIN/ ) {
$self->{InTraceBlock} = TRUE;
$self->{LastBegin} = $self->{LineNo};
}
return $status;
}
1;Marian HackMan Marinov Dynamic Code Generation
Filter::Simple
package BANG;
use Filter::Simple;
FILTER {
s/BANG\s+BANG/die ’BANG’ if \$BANG/g;
};
1;
Marian HackMan Marinov Dynamic Code Generation
Filter::cpp
use Filter::cpp;
#define FRED 1
$a = 2 + FRED;
print "a = $a\n";
#ifdef FRED
print "Hello FRED\n";
#else
print "Where is FRED\n";
#endif
Marian HackMan Marinov Dynamic Code Generation
Thank you
Questions ?
Additional readinghttp://www.bytelabs.org/pub/papers/hburg07.pdf
Contact me:
Marian HackMan Marinov
mm [maybe at] 1h.com
icq: 7556201
irc: irc.freenode.net HackMan
jabber: [email protected]
Marian HackMan Marinov Dynamic Code Generation