in reply to Re^3: PAR::Packer generated EXE that was detected as a trojan...
in thread PAR::Packer generated EXE that was detected as a trojan...

I work in security and have found pp par packed files that drop bitcoin and monero miners as well as a remote access trojan. The user created perl script is extractable and benign and the malicious code appears to resided somewhere outside of the user script, although I've not identified specifically where yet. The source is most likely the packer, so recommendation is to check the source of your packer as there may be malicious versions in the wild that insert malicious code into your compiled perl executables. Note, the code is highly resistant to sanbox analysis and carries out a good deal of VM enumeration so YMMV in getting it to run and do malicious things outside of bare metal execution.
  • Comment on Re^4: PAR::Packer generated EXE that was detected as a trojan...

Replies are listed 'Best First'.
Re^5: PAR::Packer generated EXE that was detected as a trojan...
by haukex (Archbishop) on Mar 12, 2019 at 09:03 UTC
    ... although I've not identified specifically where yet. ... there may be malicious versions in the wild that insert malicious code into your compiled perl executables.

    Sorry, but without specifics, this smells like FUD. Most people are likely to get their PAR::Packer from CPAN. The list of mirrors can be parsed by e.g. CPAN::Mirrors. If something were to be found there, then action would need to be taken.

      So to satisfy my curiosity (earlier today) I put the following together in a few minutes, excuse the mess:

      #!/usr/bin/perl use strict; use warnings; use CPAN::Mirrors; use LWP::UserAgent; use Digest::SHA qw(sha256_hex); my $sha256 = '8e3fccbf4c7e87c2df7c1e756fc17666a708bab8b36fd2004163756 +51d9b86e1'; my $path = 'authors/id/R/RS/RSCHUPP/PAR-Packer-1.047.tar.gz'; my $mirrors = CPAN::Mirrors->new( 'MIRRORED.BY' ); my @mirrors = $mirrors->mirrors(); my ( @goodsha, @badsha, @problemmirror ); my $ua = LWP::UserAgent->new(); foreach my $cpan ( @mirrors ){ if ( $cpan->{http} ){ print "Checking Mirror: $cpan->{http}\n"; my $url = $cpan->{http} . $path; my $res = $ua->get( $url ); if ( $res->is_success ){ my $file = $res->decoded_content( charset => 'none' ); my $file_sha = sha256_hex( $file ); if ( $file_sha eq $sha256 ){ print "Matching SHA\n"; push @goodsha, $url; }else{ print "Warning: SHA does not match!\n"; print "Got : $file_sha\nExpected: $sha256\n"; push @badsha, $url; } }else{ print "Couldn't download $url\n"; push @problemmirror, $url; } } } print "'Bad' mirrorsn\n\n" . join( "\n", @badsha ) if ( @badsha ); print "\n'Unreachable' mirrors\n\n" . join( "\n", @problemmirror ) if +( @problemmirror );

      A wget http://www.cpan.org/MIRRORED.BY, or otherwise having a copy in the same directory as this script is required. I get a few 'Unreachable' URLs (perhaps connectivity issues from here to there, rather than genuine downtime, see also http://mirrors.cpan.org/, the same 4 at time of writing), and a few 'BAD' SHAs. On inspection these seem to be sending the value associated with 'sha256-ungz' (as listed in CHECKSUMS), as yet I'm unsure why.

      Obviously this does not take into account PPM repos, which I gave up on years ago for unrelated reasons.

      Update: For clarity, the script downloads PAR-Packer-1.047.tar.gz from each mirror and calculates the SHA256 and validates it against a known good SHA for the file. For a few of the sites the download of the tar.gz results in a different SHA:

      Checking Mirror: http://mirrors.gossamer-threads.com/CPAN/ Warning: SHA does not match! Got : d339d474e8a87ceb3e0ad456acd13249e7e80eea0d735aed3a32108bdcfc +85bd Expected: 8e3fccbf4c7e87c2df7c1e756fc17666a708bab8b36fd200416375651d9b +86e1

      Note that d339d474e8a87ceb3e0ad456acd13249e7e80eea0d735aed3a32108bdcfc85bd is the sha256-ungz SHA: 'sha256-ungz' => 'd339d474e8a87ceb3e0ad456acd13249e7e80eea0d735aed3a32108bdcfc85bd', (from CHECKSUMS)

        Very nice, thank you! I'm not sure why you're getting different checksums, maybe something in the pipeline is uncompressing the gzipped files? I didn't have that problem with HTTP::Tiny.

        Here's my version, that tries to cover pretty much all the bases (except maybe FTP). Using it, I verified that all the CPAN mirrors I could reach are serving the same PAR-Packer-1.047.tar.gz file.