Tuesday, June 30, 2009

Jsunpack-n update: Automatic shellcode detection and other improvements

Hey guys,
I just released jsunpack-n version 0.1c. This release introduces JavaScript variable enumeration using a new file "post.js". get the source code here

Check out the new output for the sample-pdf.pcap included in the archive:

$ ./jsunpack-n.py sample-pdf.pcap
[0] decoded 25275 trughtsa.com/img/pfqa.php
[1] decoded 12269 trughtsa.com/img/pfqa.php
identified shellcode of length 1533
XOR key [shellcode]: 33
exploit_watch append [shellcode] http://trughtsa.com/img/uet.php
Match signature [CVE-2007-5659] Collab.collectEmailInfo
Match signature [CVE-2009-0927] Collab.getIcon
Match signature [CVE-2008-2992] util.printf
Match signature [CVE-2009-1493] spell.customDictionaryOpen
Match signature [CVE-2009-1492] getAnnots

undefined variable s fixing


Notice how jsunpack-n identified the shellcode, identified that it uses an XOR key of 33, and determined the URL that the shellcode presumably tries to download and execute. This URL is automatically added to the exploit_watch variable, so that a new alert will result if the victim downloads that file.

Other great features, such as default definitions for undefined variables indicated by the debug output shown above by "undefined variable s fixing".

Yet another feature, evaluation timeouts will prevent infinite loops and scripts that consume too much time/cpu/memory.

Wednesday, June 24, 2009

Jsunpack-n updates for PDF decoding, improved HTTP handling, dynamic JavaScript and Logging

Hey everyone,
I released jsunpack-n version 0.1b today (get source code from http://jsunpack.jeek.org/jsunpack-n.tgz). While this code is still being released as alpha/unstable, there are some great new features in this edition.

For example, try to decode the sample-pdf.pcap file included with the distribution and you will notice that I've added not only PDF decoding, but minimal PDF CVE signatures.

$ ./jsunpack-n.py sample-pdf.pcap
decoded 25275 bytes in pdf
[0] decoded 25275 trughtsa.com/img/pfqa.php
[1] decoded 7627 trughtsa.com/img/pfqa.php
Match signature [CVE-2007-5659] Collab.collectEmailInfo
Match signature [CVE-2007-5659] Collab.getIcon
Match signature [CVE-2008-2992] util.printf
Match signature [CVE-2009-1493] spell.customDictionaryOpen
Match signature [CVE-2009-1492] getAnnots


I hope you enjoy all of the new features in this update. As always, I like feedback so send me an email blake_at_jeek_org.

Sunday, June 7, 2009

Very Cool jsunpack-n release: JavaScript Decoding on the Network (The Future)

My favorite tools to decode JavaScript today are for security research and often have too little impact because administrators must find URLs, submit them for research, and it requires significant additional effort. There is no current way to detect threats against a real network using these tools in an automatic manner.

Until now! I started building a tool that is useful to administrators defending networks. The main difference is that it is a completely passive JavaScript decoder to perform Intrusion Detection, by processing network traffic (either an interface or pcap file), rather than URLs.

I built a basic implementation of this concept as a new version of "jsunpack-network" or (jsunpack-n). Some of the benefits of this technique are:

  • Tracks streams and decodes Transfer and Content encodings of types chunked and gzip.

  • Completely passive: Don't need to worry about User-Agents, proxies, or other tricks that attackers use to prevent analysis

  • Detect if an exploit is successful: the system monitors all URLs. It can determine if an exploit would fetch another URL and when the client requests that URL, the system knows that the exploit was successful.



The source code for this project is available from http://jsunpack.jeek.org/jsunpack-n.tgz. Here is an example output using the test file (included in the jsunpack-n.tgz archive):

$ ./jsunpack-n.py sample-http-exploit.pcap
DECODED JavaScript Data
exploit_watch append hxxp://hifgejig.cn/nuc/exe.php


The exploit_watch variable tracks all URLs to track if an exploit is successful and if it is, then the script prints the associated IP addresses and URLs:

print 'Exploit Successful ', tcp.addr, ' from URL ', exploit_watch[host+url]

Since this project is very new, I expect there will be a few issues and therefore you run this at your own risk. I am releasing this code as alpha/unstable, because I think that there is a lot of opportunity to improve it.

Two of the areas that are completely lacking at this point are

  • signature-based detection

  • pdf decoding



I am releasing a PDF decoding script with this code, available in the jsunpack-n.tgz archive called "pdf.py"; however, I haven't integrated it with jsunpack-n yet. While this should be a simple task, I'm still testing and improving the PDF decoding, as it now only handles a few of the decoding techniques I'd like it to support.

Please leave me your comments (good or bad), to improve the project. I haven't fully integrated jsunpack's algorithms yet (I will soon, I promise).

Improved Command Line API for jsunpack

A few weeks ago Jesse wrote an excellent script which is a command line interface for jsunpack.

Last week, one reader made some great improvements to this script by allowing you to upload a local file for decoding. It checks each command line argument to see if a local file exists, then if it does it uploads it. Otherwise, it works in the same way as Jesse's original script and just decodes URLs.


#!/usr/bin/perl

use strict;
use CGI;
use LWP::Simple;
use LWP::UserAgent;
use HTTP::Request::Common;

my $ua = LWP::UserAgent->new;
$ua->agent("jsunpack");

for my $url (@ARGV){
if (-f "$url"){
if(open(FIN, "< $url")){
$url = <FIN>;
close(FIN);
}
else {
print "warning: ignoring '$url', cannot open file\n";
}
}

my $res = $ua->post(
'http://jsunpack.jeek.org/dec/api',
Content_Type => 'application/x-www-form-urlencoded',
Content =>
[
'url' => [$url],
'apikey' => ['exploitme']
]
);

if ($res->is_success){
print $res->content;
}
else {
print "\n\n"."Failed to fetch remote file"."\n\n";
print "jsunpack"."\n".$res->status_line, "\n";
}
}

Monday, May 18, 2009

PDF Decoding Bugfix and Open Source from Adobe

I fixed a bug today, which was causing some of the scripts to fail decoding.
Basically, the JavaScript contained within a PDF file can be part of a special tag where it escapes special characters like (, ), &, \, and so on. The problem with this is that some of the regular expressions would incorrectly show up like this:
(hOPz).replace(/\\&/g,BiY+(13+20-8))
p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c])

In those cases, you could make them function correctly by replacing '\\' with a single '\' fixes the problem.
(hOPz).replace(/\&/g,BiY+(13+20-8))
p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])


This bug has been corrected in any future decodings see examples here and here.

I originally thought this might be related to custom Adobe Reader javascript engine, since Adobe uses a custom version of SpiderMonkey. I would still like to integrate Adobe reader's custom JavaScript engine whenever processing PDF files, however, their website says
In some Adobe products, Adobe uses a modified version of the open source SpiderMonkey code. Use of that source is subject to the Mozilla Public License Version 1.1 (the License). You may obtain a copy of the License on the Mozilla website or in the download files.

However, read on and you will see "Download files - Coming soon!". There goes that plan! Anyone at Adobe care to comment on when they plan to release this code?

Thursday, May 14, 2009

Command Line API for jsunpack

Thanks Jesse!
Yesterday, he sent me this script, which takes URLs as parameters then provides the decoding as output. The "api" script does not escape HTML characters whenever the User-Agent is "jsunpack" and the parameter "apikey=exploitme" is set (to prevent accidental accesses of a malicious page).

#!/usr/bin/perl -w
use strict;
use CGI;
use LWP::Simple;
use LWP::UserAgent;
use HTTP::Request::Common;

my $unpackurl = 'http://jsunpack.jeek.org/dec/api?url=';
my $apikey = '&apikey=exploitme';

my $ua = LWP::UserAgent->new;
$ua->agent("jsunpack");

for my $url (@ARGV){
my $req = HTTP::Request->new( GET => ($unpackurl . CGI::escape($url) . $apikey));
my $res = $ua->request($req);

if ($res->is_success){
print $res->content;
}
else {
print "\n\n"."Failed to fetch remote file"."\n\n";
print "jsunpack"."\n".$res->status_line, "\n";
}
}


One feature that could improve this script would have it POST the contents of a local file. Does anyone feel like doing some scripting to extend this?

Wednesday, May 13, 2009

Using ClamAV on the command line as an automatic unpacker

A few people have asked me about how exactly the automatic unpacking in jsunpack works whenever it finds an executable. Well, here is the answer.

Take this executable submitted on 05/13/09 as an example:
Sections ( UPX0 UPX1 UPX2 )
File: MS-DOS executable PE for MS Windows (GUI) Intel 80386 32-bit, UPX compressed
Strings:5.com/
Strings:.NET CLR
Strings:UNPACKED %sc%sok.com/
Strings:UNPACKED %sm0%s09.biz
Strings:UNPACKED %sn%s9.info
Strings:UNPACKED c:\43214354.bat
Strings:UNPACKED Us%se%sla/4.0 (compatible; MSIE 7.0; %s; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Strings:UNPACKED http://%s%s
Strings:UNPACKED c:\win
Strings:UNPACKED c:\wi%sft%df44.dat
Strings:UNPACKED %s\jopaxx_%d.exe
Strings:UNPACKED c:\w%sws\t55ft%df44.dat
Strings:UNPACKED %s\st_%d.exe
Strings:UNPACKED %s\yoo_%d.exe
Strings:UNPACKED %s\lim_%d.exe
Strings:UNPACKED c:\windows\%s%s.exe
Strings:UNPACKED reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable /t REG_DWORD /d 00 /f
Strings:UNPACKED reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable /t REG_DWORD /d 00 /f
Strings:UNPACKED www.google.com
Strings:UNPACKED 127.0.0.1
Strings:UNPACKED Software\Microsoft\Windows\CurrentVersion\Internet Settings
Strings:UNPACKED tmp_%d_%d.exe
Size: 14848 bytes,
MD5: 78d18e15a1ce15d4869f8db16f4e8642


UPX isn't particularly impressive because "upx -d" works fine most of the time, but this method gets a lot of other packed files too. It uses clamscan (from clamav.net) with --leave-temps, then it looks for URLs, Registry keys, domain names, and anything else interesting it could find in the strings. If it finds the same string in the original binary, then it does not display UNPACKED before outputting it. In this way, the analyst can see if it was really hidden or available in the original strings output.

The --leave-temps method is not perfect, but it has helped me on a number of occassions when I was in a hurry to evaluate the likelihood that a binary was malicious or find the purpose of an unknown binary or large number of malicious samples. In particular, I found it the most useful when it finds an autoit-compiled executable. In those cases, you get the entire autoit script from taking this simple step, which is much easier to quickly analyze.