PDA

View Full Version : Reversing compiled perl files


seras
January 10th, 2008, 04:40
Has anybody had a shot at looking at reversing perl files compiled into executables on Linux?

Quick searches of google/other search engines/this forum show a few engines like perl2exe have already been broken, but what about things like perlcc, etc?

Looking at a commercial product and analysing some of their internals which I can't get at the source code for as part of an audit.

Interesting enough, a quick run through with strings shows that some of the source code may still be intact:

Quote:
@modparts
$modfname
$modpname
$try
$bootname
$libref
@unresolved
$boot_symbol_ref


however it does look like the perl interpreter may be in here too:

Quote:

PERL_API_REVISION='5'
PERL_API_SUBVERSION='0'
PERL_API_VERSION='5'
PERL_REVISION='5'
PERL_SUBVERSION='2'
PERL_VERSION='6'
RCSfile='$RCSfile'
Revision='$Revision'
SUBVERSION='2'
...
installbin='/usr/bin'
installman1dir='/usr/man/man1'
installman3dir='/usr/man/man3'
installprefix='/usr'
installprefixexp='/usr'
installscript='/usr/bin'
installsitearch='/usr/lib/perl5/site_perl/5.6.2/i686-linux'
installsitebin='/usr/bin'
installsitelib='/usr/lib/perl5/site_perl/5.6.2'
installstyle='lib/perl5'


EDIT: Just about to run through this with IDA to see if it dumps anything in memory, but thought I'd put the post up to see if anyone had any resources I could read over

blabberer
January 10th, 2008, 06:24
Quote:
[Originally Posted by seras;71651]Has anybody had a shot at looking at reversing perl files compiled into executables on Linux?



yes me just a few minutes back

Code:

*server:~> perlcc
/usr/bin/perlcc: Usage:
/usr/bin/perlcc [-o executable] [-r] [-O|-B|-c|-S] [-I /foo] [-L /foo] [-log log] [source[.pl] | -e oneliner]
*server:~> md perlcrap
*server:~> cd perlcrap/
*server:~/perlcrap> perlcc -e 'print "hello world. " ' -o hello-bin
pccR8DLH.c: In function `perl_init_aaaa':
pccR8DLH.c:796: warning: this decimal constant is unsigned only in ISO C90
*server:~/perlcrap> ls
hello-bin
*server:~/perlcrap> ./hello-bin
hello world. *server:~/perlcrap>


yeah it might have some strings about perl interpreter so what

Code:

server:~/perlcrap> strings hello-bin | grep -i 'perl_I'
Perl_Iperl_destruct_level_ptr
Perl_Iinitav_ptr
Perl_Iamagic_generation_ptr
Perl_Iincgv_ptr
Perl_Imain_cv_ptr
Perl_Iregex_padav_ptr
Perl_Isv_undef_ptr
Perl_Iendav_ptr
Perl_Imain_root_ptr
Perl_Imain_start_ptr
Perl_Iregex_pad_ptr
Perl_Icompcv_ptr
Perl_Idowarn_ptr


it also shows the hello world string

Code:

strings hello-bin | grep -i 'hello'
hello world.


file shows its an executable and it runs
Code:

file hello-bin
hello-bin: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped

./hello-bin
hello world.


we can find where we can patch this crap like this

Code:

server:~/perlcrap> objdump -d -M intel hello-bin | grep -i 'main'
0804df90 <main>:
804dfd1: 75 54 jne 804e027 <main+0x97>
804dfe4: 75 0a jne 804dff0 <main+0x60>
804e032: 7e 02 jle 804e036 <main+0xa6>
804e034: eb 6c jmp 804e0a2 <main+0x112>
804e0a0: eb 8c jmp 804e02e <main+0x9e>
804e153: 7c 02 jl 804e157 <main+0x1c7>
804e155: eb 28 jmp 804e17f <main+0x1ef>
804e17d: eb ce jmp 804e14d <main+0x1bd>



works pretty fine in gdb

Code:

gdb $ disassemble main main+30
Dump of assembler code from 0x804df90 to 0x804dfc0:
0x0804df90 <main+0>: push ebp
0x0804df91 <main+1>: mov ebp,esp
0x0804df93 <main+3>: push ebx
0x0804df94 <main+4>: sub esp,0x24
0x0804df97 <main+7>: and esp,0xfffffff0
0x0804df9a <main+10>: mov eax,0x0
0x0804df9f <main+15>: sub esp,eax
0x0804dfa1 <main+17>: sub esp,0x8
0x0804dfa4 <main+20>: push 0x1
0x0804dfa6 <main+22>: push 0x8
0x0804dfa8 <main+24>: call 0x8049824
0x0804dfad <main+29>: add esp,0x10
0x0804dfb0 <main+32>: mov ebx,eax
0x0804dfb2 <main+34>: sub esp,0xc
0x0804dfb5 <main+37>: push 0x0
0x0804dfb7 <main+39>: call 0x80498a4
0x0804dfbc <main+44>: add esp,0x10
0x0804dfbf <main+47>: mov DWORD PTR [eax],ebx
End of assembler dump.
gdb $


so get cracking patch,edit,crash generate coredumps debug it and there you get your resources

seras
January 10th, 2008, 06:49
Unfouranetly this one is stripped (to be expected), just means a bit more digging around I guess..

Code:
[root@ole /s/rce/]# strings target | grep -i 'perl_I'

[root@ole /s/rce/]# strings target | egrep -i '^perl'
Perl_gv_stashpv
perl_get_sv
Perl_croak
Perl_markstack_grow
Perl_save_int
Perl_sv_setiv
Perl_av_store
Perl_pregcomp
Perl_mg_set
Perl_gp_free
...
... output cut for brevity
...
Perl_sv_setpvn
perl_free
perldig
perlmain.c
PERL_API_REVISION='5'
PERL_API_SUBVERSION='0'
PERL_API_VERSION='5'
PERL_REVISION='5'
PERL_SUBVERSION='2'
PERL_VERSION='6'
perl5='/usr/bin/perl'
perl=''
perllibs='-lnsl -ldl -lm -lc -lposix -lcrypt -lutil'
perlpath='/usr/bin/perl'
PERL_DL_NONLAZY

[root@ole /s/rce/]# objdump -d -M intel target | grep -i 'main'
080496b0 <__libc_start_main@plt>:
80497fc: e8 af fe ff ff call 80496b0 <__libc_start_main@plt>

[root@ole /s/rce/]# file target
target: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.0.0, dynamically linked (uses shared libs), stripped


Interesting enough instead of main, there are a few sections like this:

Code:
[root@ole /s/rce/]# objdump -d -M intel target
...
target: file format elf32-i386

Disassembly of section .init:

080493fc <_init>:
80493fc: 55 push ebp
80493fd: 89 e5 mov ebp,esp
80493ff: 83 ec 14 sub esp,0x14
8049402: 53 push ebx
8049403: e8 00 00 00 00 call 8049408 <_init+0xc>
8049408: 5b pop ebx
8049409: 81 c3 68 ed 15 00 add ebx,0x15ed68
804940f: 83 bb fc ff ff ff 00 cmp DWORD PTR [ebx-4],0x0
8049416: 74 05 je 804941d <_init+0x21>
8049418: e8 a3 03 00 00 call 80497c0 <__gmon_start__@plt>
804941d: 8d 76 00 lea esi,[esi]
8049420: e8 3b 04 00 00 call 8049860 <dlopen@plt+0x90>
8049425: e8 a6 17 14 00 call 818abd0 <dlopen@plt+0x141400>
804942a: 5b pop ebx
804942b: c9 leave
804942c: c3 ret
Disassembly of section .plt:

08049430 <Perl_gv_stashpv@plt-0x10>:
8049430: ff 35 74 81 1a 08 push ds:0x81a8174
8049436: ff 25 78 81 1a 08 jmp ds:0x81a8178
804943c: 00 00 add BYTE PTR [eax],al
...

08049440 <Perl_gv_stashpv@plt>:
8049440: ff 25 7c 81 1a 08 jmp ds:0x81a817c
8049446: 68 00 00 00 00 push 0x0
804944b: e9 e0 ff ff ff jmp 8049430 <_init+0x34>

08049450 <perl_get_sv@plt>:
8049450: ff 25 80 81 1a 08 jmp ds:0x81a8180
8049456: 68 08 00 00 00 push 0x8
804945b: e9 d0 ff ff ff jmp 8049430 <_init+0x34>


And here's the list of sections

Code:

Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000013 08048114 08048114 00000114 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 08048128 08048128 00000128 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .hash 0000028c 08048148 08048148 00000148 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynsym 000005e0 080483d4 080483d4 000003d4 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynstr 0000069c 080489b4 080489b4 000009b4 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .gnu.version 000000bc 08049050 08049050 00001050 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version_r 00000050 0804910c 0804910c 0000110c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .rel.dyn 000000d0 0804915c 0804915c 0000115c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rel.plt 000001d0 0804922c 0804922c 0000122c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .init 00000031 080493fc 080493fc 000013fc 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .plt 000003b0 08049430 08049430 00001430 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .text 00141414 080497e0 080497e0 000017e0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .fini 0000001c 0818abf4 0818abf4 00142bf4 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .rodata 0001c402 0818ac10 0818ac10 00142c10 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
14 .eh_frame 00000004 081a7014 081a7014 0015f014 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
15 .ctors 00000008 081a8018 081a8018 0015f018 2**2
CONTENTS, ALLOC, LOAD, DATA
16 .dtors 00000008 081a8020 081a8020 0015f020 2**2
CONTENTS, ALLOC, LOAD, DATA
17 .jcr 00000004 081a8028 081a8028 0015f028 2**2
CONTENTS, ALLOC, LOAD, DATA
18 .dynamic 00000140 081a802c 081a802c 0015f02c 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .got 00000004 081a816c 081a816c 0015f16c 2**2
CONTENTS, ALLOC, LOAD, DATA
20 .got.plt 000000f4 081a8170 081a8170 0015f170 2**2
CONTENTS, ALLOC, LOAD, DATA
21 .data 00147a60 081a8280 081a8280 0015f280 2**5
CONTENTS, ALLOC, LOAD, DATA
22 .bss 0000260c 082efce0 082efce0 002a6ce0 2**5
ALLOC
23 .comment 000000c3 00000000 00000000 002a6ce0 2**0
CONTENTS, READONLY
24 .note 0000003c 00000000 00000000 002a6da3 2**0
CONTENTS, READONLY

seras
January 10th, 2008, 07:20
I think this is getting even better... a bit further into it via IDA shows:

Code:
loc_8189834:
sub esp, 0Ch
mov eax, [ebp+arg_0]
shl eax, 2
add eax, 10h
push eax
call _Perl_safemalloc
add esp, 10h
mov [ebp+var_C], eax
mov edx, [ebp+var_C]
mov eax, [ebp+arg_4]
mov eax, [eax]
mov [edx], eax
mov eax, [ebp+var_C]
add eax, 4
mov dword ptr [eax], offset aE ; "-e"
mov eax, [ebp+var_C]
add eax, 8
mov dword ptr [eax], offset unk_818BEF1
mov eax, [ebp+var_C]
add eax, 0Ch
mov dword ptr [eax], offset asc_81A6CA7 ; "--"
mov [ebp+var_8], 1


Hoping this will work (i.e. perl -e --)

seras
January 10th, 2008, 11:00
OK - took a little while but looks like it's a patched copy of perlcc. General format of the binary appears to be (pseudoish C code):

static PerlInterpreter *my_perl; /* perl interpreter instance */

int main(int argc, char **argv, char **env)
{
my_perl = perl_alloc(); /* allocate some memory */
perl_construct(my_perl); /* init perl interpreter */
perl_parse(my_perl, NULL, argc, argv, (char **)NULL); /* load and parse the perl script */
perl_run(my_perl); /* Execute */
perl_destruct(my_perl); /* Shutdown interpreter, cleanup garbage */
perl_free(my_perl); /* free memory */
}

It's possible the byte code has been encrypted (probably ROT-13/XOR, who knows) but I'll dig further and see what the go is