Thursday, October 18, 2012

Detect changes in Virtual guest after manual malware execution

When working with manual testing/execution of malware. I quickly find myself missing the sandbox reports of changes made to the system which you get if you are using Cuckoo for example.

Sandboxes like Cuckoo are very useful,  but I prefer manual work for certain kinds of tests. It's nice to have several methods available. 

First of I would like to give some credit to a colleague of mine, for inspiring me to solve my need in the way described below, he did something similar in his setup. So thanks! =)

The script included in this post will mount a virtual image be it Virtualbox or KVM/QEMU images using qemu-tools. 

After the image is mounted, Aide which is a file and directory integrity checker
( Will identify changes made to the file system. If you like to use Samhain or Tripwire it will most likely work fine as long as you adjust the syntax in the script. 

At first run the script will check if the aide.db exist, if not one will be created and this will be the baseline for further checks. You should of course do this on a clean system.

When you have a baseline db and you have executed your malware sample and are happy with the results. Run the script against the image to see which files has been created and/or modified. Changes are also saved in a log file.

Please install the prerequisite and change paths to fit your environment.

--- script start ---

# Detect which files has been changed and/or added to a vm image. Useful for manual malware 

# detection in a sandbox environment
# v1.0 - mikael keri / @nsmfoo
prerequisites: qemu-utils, aide and root access

usage () {
  echo "usage: $0 -i image_name (inkl path) -m mount_dir -a <check|update>"

while getopts ":i:m:h:a:" option; do
  case $option in
    i)  image_name="$OPTARG" ;;
    m)  mount_dir="$OPTARG" ;;
    a)  aide="$OPTARG" ;;
    h)  usage
        exit 0
    :)  echo "Error: requires an argument: $options"
        exit 1
    ?)  echo "Error: unknown option: $options"
        exit 1

if [ -z "$image_name" ]; then
  echo "No image defined"
  exit 1if [ -z "$mount_dir" ]; then
  echo "No mount directory defined"
  exit 1

if [ -z "$aide" ]; then
  echo "No Aide command defined - valid values are check or update"
  exit 1

if [ $aide != "update" -a $aide != "check" ]; then
 echo "Valid Aide arguments are either update or check"
 exit 1

# remove trailing slash

# only load the module once
if [ -z "$(lsmod | grep nbd)" ]; then
 echo -n "Loading kernel module.."
 modprobe nbd
 sleep 5
 echo "finished!"
# mount image
echo -n "Mounting image.."
qemu-nbd -c /dev/nbd0 "$image_name"
sleep 5
mount --read-only /dev/nbd0p1 "$mount_dir"
echo "finished!"

# init the aide db if it does not exsist
 if [ ! -f /usr/local/etc/aide.db ]; then
  echo -n "Aide db does not exist. First run it will take some time .."
  aide -c /usr/local/etc/kvm_aide.conf --init
  cp /usr/local/etc/ /usr/local/etc/aide.db
echo "finished!"

 if [ "$aide" = "check" ]; then
# check for changes
   echo -n "Check for changes.."
   aide -c /usr/local/etc/kvm_aide.conf --check > changes.log
   cat changes.log
   echo "finished!"
 elif [ "$aide" = "update" ]; then
   echo -n "Updating Aide db.."
    aide -c /usr/local/etc/kvm_aide.conf --update

    cp /usr/local/etc/ /usr/local/etc/aide.db
 echo "finished!"

# umount and unload
 echo -n "Cleaning.."
 umount "$mount_dir"
 qemu-nbd -d /dev/nbd0
 echo "finished!"


--- script end ---

Example syntax:  ./ -i /var/lib/libvirt/images/johndoe.qcow2 -m /mnt -a check

/Micke @nsmfoo

Tuesday, October 2, 2012

Modifying VirtualBox settings for malware analysis part 3

 Follow up on my two previous post regarding preparing Virtualbox for malware analysis.

I hope this third post, concludes this research for a while at least ..

Please review the two earlier post before apply the settings below.

Modify the BIOS.

By adding your own DSDT image, you will be able to close a couple of more ways to detect the presence of a virtual machine. And it also makes the guest look a bit more "natural"

Start with generating a DSDT image

    sudo dd if=/sys/firmware/acpi/tables/DSDT of=DSDT.bin

Move the DSDT.bin to somewhere you see fit

   mv DSDT.bin ../VirtualBox VMs <vm name>
   sudo chown <vbox users>.<vbox user> DSDT.bin

Then run the following command to update the config for your guest

    VBoxManage setextradata "<VM name>" "VBoxInternal/Devices/acpi/0/Config/CustomTable"    <path to DSDT.bin>

Virtualbox 4.2 also enables the guest to retrieve a few more values from the host. If not set they will contain strings like "Oracle" and "Virtualbox/VBOX"

Start with retrieving some more information from your physical host:
   sudo dmidecode -t2

Sample output:

Base Board Information
    Manufacturer: <Vendor>
    Product Name: <Product>
    Version: Not Available
    Serial Number: <Serial>
    Asset Tag: Not Specified
    Features: None
    Location In Chassis: Not Specified
    Chassis Handle: <Value>
    Type: Unknown
    Contained Object Handles: 0

Set the values using the output above

    VBoxManage setextradata "<VM name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBoardVendor" "<Vendor>"
    VBoxManage setextradata "<VM name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBoardProduct" "<Product>"
    VBoxManage setextradata "<VM name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBoardVersion" "Not Available"
    VBoxManage setextradata "<VM name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBoardSerial"  "<Serial>"
    VBoxManage setextradata "<VM name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBoardAssetTag"  "Not Specified"
    VBoxManage setextradata "<VM name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBoardLocInChass" "Not Specified"

Then run dmidecode once more:

    sudo dmidecode -t3

Chassis Information
    Manufacturer: <Vendor>
    Type: Notebook
    Lock: Not Present
    Version: Not Available
    Serial Number: <Serial>
    Asset Tag: No Asset Information
    Boot-up State: Unknown
    Power Supply State: Unknown
    Thermal State: Unknown
    Security Status: Unknown
    OEM Information: 0x00000000
    Height: Unspecified
    Number Of Power Cords: Unspecified
    Contained Elements: 0

Set the values using the output above

    VBoxManage setextradata "<VM name>" "VBoxInternal/Devices/pcbios/0/Config/DmiChassisVendor"     "<Vendor>"
    VBoxManage setextradata "<VM name>" "VBoxInternal/Devices/pcbios/0/Config/DmiChassisVersion"    "Not Availible"
    VBoxManage setextradata "<VM name>" "VBoxInternal/Devices/pcbios/0/Config/DmiChassisSerial"     "<Serial>"
    VBoxManage setextradata "<VM name>"  "VBoxInternal/Devices/pcbios/0/Config/DmiChassisAssetTag"   "No Asset Information"

The above settings means that you will have to update the batch script described in previous posts

The script will now look like: 

Replace: VENDOR with your hw vendor

--- start script -------





@reg add HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System /v VideoBiosVersion /t REG_MULTI_SZ /d "VGA BIOS v1.14" /f

----  end of script ---

Thursday, September 20, 2012

Modifying KVM (qemu-kvm) settings for malware analysis

This post is long overdue, but here it is.

How to make qemu-kvm a bit harder to detect for malware and pentesters alike (ex: fool Metasploit checkvm).

 I have found that using libvirt and virsh edit is a simple way to change the settings for the guest OS.

General guidelines: 

* Don't install guest additions

* Change MAC address
        <interface type='network'>
            <mac address='xx:xx:xx:xx:xx:xx'/>
            <source network='default'/>
            <model type='rtl8139'/>
           <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>

* Copy the host CPU info into the guest. (can be done in the XML file or via virt-manager)
      Processor -> configuration -> Copy host CPU configuration

 * Change BIOS information

Start by retrieving  the dmidecode information for your host.

          <smbios mode='sysinfo'/>

      <sysinfo type='smbios'>
             <entry name='vendor'>XXXX</entry>
             <entry name='version'>XXXXXX</entry>
             <entry name='date'>XXXXX</entry>
             <entry name='release'>XXXXX</entry>

          <entry name='manufacturer'>XXXXX</entry>
          <entry name='product'>XXXXX</entry>
          <entry name='version'>XXXXX</entry>
          <entry name='serial'>XXXXX</entry>
          <entry name='uuid'>XXXXXXXX</entry> <-- This values has to be the same as the other UUID variable found in the xml file
          <entry name='sku'>XXXXXX</entry>
          <entry name='family'>XXXXXX</entry>     

* Change Harddrive model

In my quest to find an easy way to change the harddrive model number from QEMU HARDDISK to something else, I stumble up on this patch:

But the stock qemu-kvm shipped with Ubuntu does not support the "model=" setting. So I downloaded the latest qemu-kvm source, as I thought that the patch would be incorporated in that release. Sadly I did not get it to work quickly (adding it as a qdev option might have worked)

It could have been that libvirt version which is shipped with Ubuntu did not  support me adding the setting via virsh  ..anyway a quick fix to the problem was to edit core.c and replace "QEMU HARDDISK" with something else as I already had the source.

   Edit file:    qemu-kvm-1.2.0-rc2/hw/ide/core.c
  Org:           strcpy(s->drive_model_str, "QEMU HARDDISK");
  Change:     strcpy(s->drive_model_str, "XXXXXXX");

 * Registry edit

  Change "WOOT" to something more suitable. As with Virtualbox, if you are using Cuckoo this script has to be run only once. If you need to reboot, add the script to auto execute after reboot to change those pesky registry values that are reset after each reboot.   

 -- start of script ---







@reg add HKLM\HARDWARE\DESCRIPTION\System /v SystemBiosVersion /t REG_MULTI_SZ /d "WOOT -1" /f

--- end of script ----

Update 1:  Modify the BIOS.

At the moment my blog posts reflects my research,  sporadic and a bit chaotic. Anyway I just noticed (it quite obvious really)  that the BIOS would reveal the presences of a virtual guest so here is a way to make it less obvious.

Download the BIOS (seabios) source:

   git clone git://  

Edit the following file:


Locate the following part:

#define CONFIG_APPNAME  "Bochs"

And change it to something appropriate

#define CONFIG_APPNAME4 "DELLS" (I don't know just change it to something..)

Run make and then replace the current one with the new one found in the "out" directory.

You can verify the change by using the Windows port of dmidecode, which contains a application called biosdecode.exe.

The value to look for is the OEM identifier. The change will also have some positive effect on the reg settings, in the sense that they will look more "natural"(?)


Sunday, September 2, 2012

Modifying VirtualBox settings for malware analysis part 2

I did some more research and noted that my previous post lacked some information/fixes.
If you apply the previously mentioned setting you will still be able to detected the guest, for example by using the Metasploit script checkvm.. but this can be fixed.

1) Start off with applying the previous setting for the virtualbox guest.

2) Then login to the guest and delete registry keys that is called something
like "VBOX".

On one of my guests I found the following. But you milage may vary depending on if you
added the virtualbox setting before booting the guest for the first time or not

I had VBOX related reg keys in the following locations:


There are a few keys that will be reset on reboot.

Reboot the guest and search once again in the registry to identify them.

 If you are using cuckoo this will not be a problem as you don't restart the guest between tests. However if you do manually test you could add a script that performes the changes at boot.

The batch script below is based in information bluntly stolen from:

I have added some more keys that the original script did not cover

Note: replace the string "WOOT" and "VGA BIOS v1.54" with a string of your choice.

-- start of script ---



SystemBiosVersion /t REG_MULTI_SZ /d "WOOT -1" /f
VideoBiosVersion /t REG_MULTI_SZ /d "VGA BIOS v1.54" /f

--- end of script ---

There are of course other ways to identify a Virtualbox instance (or a Cuckoo sandbox in VBox or KVM). Some can be fixed other may not be so easily solved. I will update this post with some more fixed soon.

/Micke @nsmfoo

Thursday, August 23, 2012

Modifying VirtualBox settings for malware analysis

If you are using VirtualBox for malware analysis,  either with a sandbox like Cuckoo or stand alone. You probably would like to be able to run modern malware even those samples that are VM aware.

Here are a few tips to make your VirtualBox guest somewhat harder to detect.

First run dmidecode on your host (I assume it's a Linux based one, but this can be performed on other OSes as well)

#dmidecode -t0
#dmidecode -t1

You will get an output that looks something like this:

BIOS Information
  •     Vendor: <vendor>
  •     Version: <BIOS version>
  •     Release Date: <BIOS date>
System Information
  •     Manufacturer: <vendor>
  •     Product Name: <product>
  •     Version: <hw "version">
  •     Serial Number: <S/N>
  •     UUID: <UUID>
  •     Wake-up Type: Power Switch
  •     SKU Number: Not Specified
  •     Family: <"hw "version">
To make it easier to apply these settings on several guest's, create a script that
contains the following commands:
(Populate the values with information from the Dmidecode output above)

VBoxManage setextradata  "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBIOSVendor"        "<vendor>"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBIOSVersion"       "<BIOS version>"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBIOSReleaseDate"   "<BIOS date"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBIOSReleaseMajor"  <value from BIOS date>
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBIOSReleaseMinor"  <value from BIOS date>
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBIOSFirmwareMajor" <value from BIOS date>
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiBIOSFirmwareMinor" <value from BIOS date>
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiSystemVendor"      "<vendor>"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiSystemProduct"     "<product>"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiSystemVersion"     "<product>"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiSystemSerial"      "<S/N>"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiSystemSKU"         "Not Specified"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiSystemFamily"      "<"hw version">"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/pcbios/0/Config/DmiSystemUuid"     "<UUID>"

  • Change MAC address:     
 VBoxManage modifyvm "<vm name>" --macaddressX <MAC>
  •  Change disk settings:
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/piix3ide/0/Config/PrimaryMaster/SerialNumber"  "<serial>"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/piix3ide/0/Config/PrimaryMaster/FirmwareRevision" "<firmware>"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/piix3ide/0/Config/PrimaryMaster/ModelNumber" "<model>"

  • Detach CDROM (or change settings for the CD-ROM)
  • Don't install vbox tools! 
Use:" VBoxManage getextradata "<vm name>"  enumerate " to review your settings.



Untested but might be useful..
VBoxManage setextradata "VM name" "VBoxInternal/TM/TSCTiedToExecution" 1

Wednesday, July 4, 2012

Perl script to push samples to Virustotal (93% stolen code =))

Just a quick post for a quick fix. I added a few lines to the Perl script originally made by cfrenz to make it more useful for my needs and hopefully for a few others as well. Looping through a JSON file can be tricky and the original script lacked the more verbose output which is now included.


# This script is heavily based (to say the least) on the work done by cfrenz ( My aim was to add some functionality to the original script. 

# Usage: <sample> or just do a loop through your sample repository and pipe the result to a file(s) for later 
# analyses. Which makes it easy to push loads of samples to VT.
# /Micke @nsmfoo

# Org comments:
# Copyright 2012- Christopher M. Frenz
# This script is free software - it may be used, copied, redistributed, and/or modified
# under the terms laid forth in the Perl Artistic License

use LWP::UserAgent;
use JSON;

#Code to submit a file to Virus Total
my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 1 });
my $url='';

my $key='VT-API KEY';

my $response = $ua->post( $url,
    Content_Type => 'multipart/form-data',
    Content => ['apikey' => $key,
    'file' => [$ARGV[0]]]
die "$url error: ", $response->status_line
   unless $response->is_success;
my $results=$response->content;

#pulls the sha256 value out of the JSON response
my $json = JSON->new->allow_nonref;  
my $decjson = $json->decode( $results);
my $sha256=$decjson->{"sha256"};

#Code to retrieve the results that pertain to a submitted file by hash value

$response = $ua->post( $url,
    ['apikey' => $key,
    'resource' => $sha256]
die "$url error: ", $response->status_line
   unless $response->is_success;

$json = JSON->new->allow_nonref;  
$decjson = $json->decode($results);

# print selected values from the json file
print "-----------------------------------------------------------------------\n";
print "Sample name: ". $ARGV[0]."\n";
print "Scan ID:  ".$decjson->{"scan_id"}."\n";
print "Scan Date:  ".$decjson->{"scan_date"}."\n";
print "SHA256: ".$decjson->{"sha256"}."\n";
print "MD5: ".$decjson->{"md5"}."\n";
print "Detection rate: ".$decjson->{"positives"}. "/".$decjson->{"total"}."\n";
print "Verbose Message: ".$decjson->{"verbose_msg"}."\n";

print "-----------------------------------------------------------------------\n";
# print AV engines status per vendor
print "Scan results: \n";
for my $key1 ( sort keys %$decjson ) {
        for my $key2 ( sort keys %{$decjson->{ $key1 }} ) {
            print "\t$key2\n";
            for my $key3 ( sort keys %{$decjson->{ $key1 }->{ $key2 }} ) {
                print "\t\t$key3 => $decjson->{ $key1 }->{ $key2 }->{ $key3 }\n";


print "\nURL: ".$decjson->{"permalink"}."\n";

Monday, June 25, 2012

Optimizing malware sample detection

Submitting a sample to Virustotal (usually) means that it will trickle
down to the various AV vendors for detection

Depending on your organizations needs, you might have to struggle with
not only internal clients but also the dreaded external clients. 

External clients are tricky as in most cases you are not able to control them at all or you most likely don’t know which kind of AV protection they have (if they have any that is)

Enters Virustotal, which enables you to spread knowledge and hopefully detection to “all” AV vendors at least that is the idea.

I was told that samples sent to VT would not propagate to the vendors if less then two vendors detected the sample, this was a couple of years ago mind you.

So armed with the knowledge that you need some kind of "basic detection" to be able to get the attention of the AV vendors (I will leave out Flame which everyone jumped on ;)).

The solutions for this, has been to utilize the in-house AV vendors to “kick start” the detection.

Most companies big and small have at least one subscription/contract with an AV vendor, many have several different vendors (client/server, mail, proxy etc). These are companies that are present (most likely) on Virustotal. But VT is not the place to start if you need detection fast!

If you need detection in a timely fashion, you should use the SLA you pay for from your AV vendor(s).

This is how I usually do:

You begin with having “your” AV vendor(s) create detection for your sample and then you push it to Virustotal for the rest to pick up.

I also usually make direct submits to different AV vendors, using the different methods they offer on their websites as they seems to have different priorities for the different channels the receive samples from and VT seems not always to be prioritized..

So to be successful in you detection campaign, start off with the
services you pay for then continue with the free to get better coverage.

I double checked my VT fact just a couple of days ago and the current
situation is that you need at least one vendor to detect the sample for it to “spread”, but there are differences between vendors and vendors. 

Lesser know ones would not trigger the bigger players to react (this is my own interpretation of what I was told) and even then it's finally up to the
receiving AV company to decide if they would like to react on the sample or not.

If you have another recipe for success, please let me know. I’m always interested in how others are doing their “AV submit optimizing”


Monday, May 7, 2012

Online malware site checks. Part 2

Part 2

A couple of years back I had the opportunity to have a mail conversation with a person working for Bluecoats webfilter team.

I had raised a question regarding why all their checks was done from a IP range registered to them (truthfully is was a range belonging to Cerberian which was a webfilter company acquired by BC).

Their answer was not satisfying as they told me that they had not seen any reason or attempts to block their check based on their IP range. This was a round the time of the Storm botnet and my experience at that time was clearly different.

I'm in no aspect a professional malware "hunter", but I do basic malware analyses quite regularly.  And I was forced quite early to start using multiple user agents and or IP addresses to be able to download a sample. So the use of a static IP range was strange to say the least.    

As this was a couple of years ago and I have not really given it any thought on how the different commercial webfilter and online scanners, like then ones different AV vendors and security researcher make public works since then.  Many whom I tend to use quite regularly. How they solve the challenges with malicious sites only serving content to specific user agents, geographic location etc.

Bottom line is that you now a days only get one shot to retrieve content from a malicious site from a single IP (OK not every time but to often to be ignored) also you must be using the right components (OS, Web browser, plugin etc) to be able to "access" the malware

So I decided to check how a handful of different online resources did when they verified the content of a site. I installed a basic web site on a server that I had to my disposal.

The next step was to scan the site from the different resources(14 different) and then verify the result using the web logs.

I did multiple scans with the same solution  to see if I would get different results.  And the result reviled that it would not require all that much work to assemble a working blacklist to prevents these solutions from looking at the content of my site. Against webfilters this could also be used in a less malicious way for site owners to display false content to them, thus circumventing their category blocking.

* Most used IP ranges registered to the company in question
* The solutions that was using Google infrastructure had appIDs that made them easy to fingerprint.
* Some had the service name in their user agent
* Most only used one user agent variant.

The problem as I see it, based on the result was that it was quite trivial to build an effective blacklist to prevent the companies from looking at your content. I did not see any evidence of a really efficient analyze with multiple IPs and multiple user agents to maximize the likelihood of being served malware.

This might this be a case of me wishing that these service would be something they aren't? Not sure
, but quite a lot of people(myself included) look to these services to either protect us (webfilter) or to give us a verdict if the site is OK or not.

My initial thought was that I might be missing something(this would not have been the first time..),
As a prof of concept I modified the site to show different content to different visitors (applying the blacklist I had created), this would be what I would have done if I was trying to increase the life span of my malicious site. 

The longer it takes for me to get detected the more installs I get

And with the exception of bonus visitors from Virustotal "partners" I was able to apply the blacklist successfully. 

Note: If you think that this is me giving malware distributors a nice manual on how to evade detection. Then you are "flattering" me. But this is hardly something "they" have not thought of before. In fact here is a nice write-up of a exploit kit that does exactly this:

Tested services:

  • IP: static
  • User agent: "-"
  • Note: Seems specialized to scan a direct file and not a whole "site" ..

  • IP: The user can choose between a number of location from where the scan can be performed. Which is great, but in the end it only delays the blacklist creation as they are static
  • User agent:
    Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5)Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
  • Note: Even thought you chose one location there will also be requests from "the main location" followed by request from the location you chose. Also some request will include "" in the referrer field.
  • IP: static (registered to Comodo)
  • User agent:   
          Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US

  • IP: static
  • User agent: "-"
  • IP: Somewhat static (registered to Google)
  • User agent:
Mozilla/5.0 (X11; U; Linux i686; en-US; rv: Gecko/20110422 Ubuntu/10.04 (lucid) Firefox/3.6.17 AppEngine-Google; (+; appid: virustotalstorage)
  • Note: The appID is a tell tell sign =). As a bonus, if you check your "malicious" site with Virustotal you do attract the attention of others. For example Panda AV(Pandasecurity) who also likes to scan from their own IP range. But there are others who use dialups and changing user agents, so that was positive. I even got one who seemed to be using SUSE which is novel(phun intended) and the person/script behind those requests did a full scan which was admirable!(but the result should be a bit limited due to the "lack" of Linux malware) but would catch a injected iframe or similar.

- (
  • IP: Multiple (one registered to - but the IP addresses are static
  • User agent:
       "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"

  • IP: uses Google services
  • User agent:
"Mozilla/5.0 (compatible; Windows) AppEngine-Google; (+; appid: unmask-parasites)"
  • Note: The appID is yet again a give away.

- Webpawet
  • IP: Random /24 address registered to the University that hosts the solution
  • User agent: 
        "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
  • Note: You are able to set not only referer but also headers

  • IP: static and registered to a security company
  • User agent:
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv: Gecko/20101203 Firefox/3.6.13"
  • Note: URLquery allows you to set referer and change user agent

- Sucuri
  • IP: Multiple IPs(2). IP number one, is most used (points to the scanning service). IP number 2 could be a manual verification attempt.  
  • User agent:
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 MSIE 7.0"
or via google

  • Note: The referrer field includes the name of the scanning service used.

- (Websense)
  • IP: Multiple IP's (one more frequently used then the other, could be a manual verification that generated hits from IP number two)
  • User agent:
Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727)"

- Bluecoat
  • IP: static (static net) Registered to Bluecoat
  • User agent:
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; MS-RTC LM 8; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)" 

  • IP: Static IP
  • User agent:
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)" 
  • Note: Has a option to scan all links which is great.

- Trend Micro
  • IP:  Multiple IP addresses from a  /16 registered to Trendmicro
  • User agent:
         Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

- Misc
  • The people at Bitdefender does site checks from IP's registered to their company..
  • The same goes for AVG

So what can be done?  

As a provider of services: 

* Balance your checks between multiple IP addresses. Get your self a "large" amount of cheap connection (ones with dynamic IP addresses would be preferred, VPN services, TOR. The bottom line is to make creating a blacklist to hard/costly/ineffective.

* Be as compliant regarding user agents settings as possible, as the purpose is mimic regular user visits. Mix and shake well!

As a users:
* (Try to) Download the malware yourself and then use services like Webpawet or Virustotal to learn more.

Update 1: I was rightfully informed that webpawet allows you to set referer and headers. URLquery also allows you to set referar and change user agent (thanks @c_APT_ure for pointing this out)


Monday, April 30, 2012

Online malware site checks. Part 1

Part 1

 If a company would ask me for advice on how to increase their client security, my answer would be to install a webfilter!

With a webfilter, I mean a filter that is able to blacklists malicious sites, thus preventing users access to those resources.

Removing common vulnerable client application is also a effective way to achieve higher client security. But removing Flash, Java or Reader in a corporate environment even thought it would dramatically decrease the exposure to malicious code. Is in most environments not a feasible solution due to dependencies and users expectations (at least in my experience).

A webfilter blocking users from accessing know malicious sites is in most cases transparent to the end user, except when his/her favorite blog is blocked due to infection.

When installed as a perimeter protection, it's trumps a gateway antivirus solution (yet again in my experience) the reason being, that instead of having to detect each and every one of the malicious samples found in a exploitkit on a given site. Simply denying access to that site, enables you to focus on other things than worrying about if something slipped pass your gateway AV installation(and sadly maybe even your client AV).

One could argue that a webfilter suffers from the same problem as signature based antivirus, that the malicious site has to be known in order for it to be added to the blacklist.

While this is true, I would argue that the effort to determine if a site is malicious would in most cases be much quicker than understanding a malicious sample and write a efficient signature for it (also one has to take into consideration that malware could be using polymorphic functions to evade signature based detection, which would make the effort greater for the AV analyst).

Also as mentioned above, the AV have to catch them all, if one slips through the cracks it is game over!

 So .. are webfilters and oneline site checks flawless?  Of course not! In reality there is a lot of things one could wish for in these solutions. 

Stay tuned for part 2, where my praise for webfilter will suffer a blow =)

 (but I still think that the above analyze has some merit)


Saturday, April 7, 2012

Detecting honeypots using unique binaries

Most of us use online services like Virustotal, Threatexpert etc to get a quick analyze of newly "acquired" malware, it's fast and can quickly help us distinguish known malware from the not so known ones.

Virustotal had a functions, back in the day to enable the uploader to disallow VT to spread the sample to the connected AV vendors. This functions was abused by malware authors and thus removed.

The current situation is that all malware uploaded to VT is easily searchable for both security researchers and malware creators/distributors alike.

My idea or rather my thought (This might not be so novel and yes others have come to the same conclusions before) was that this creates a "great" way for an attacker to learn when he/she is discovered or a way to detect honeypots using unique binaries.

If malware authors starts to uses unique binaries(if they have not already..) not only as today to lure AV vendors but to pinpoint infections points and adversaries, this could have a very harming effect on security research as a whole. SPAM distributors have been using uniqueness as a way to verify email accounts for years.

This method could be extended to web applications attacks as well, using unique strings and data mine reports from the security community. And then it's just a matter of remembering which binary or web request was sent to which host.

A simple PoC has been developed that can detect the Dionaea honeypot (with VT submit enabled, it queries VT for verification) or other SMB honeypots.

The use of Dionaea was mostly because I have a couple of installations running, but this can be used against any kind of honeypot (as long as it(or the admin) shares information that you can data mine).

I hope this gives you some idea, about the pitfalls with information sharing. Which is a wonderful "tool" for researcher to gain knowledge from systems besides their own, but it can also tip of a attacker that you are on to them. So if you get compromised, uploading the malware to VT might not be the help you where looking for.

The script below will most certainly not make it into the Nmap NSE script library as it uses a couple of shell functions, but it will work under most *nix variants. It also required a valid VT API key which you can get from the VT site.  

You will also have to configure the script to use a binary of your choice. And one last thing I somewhat deliberately did not create this script for speed. Default sleep time for the script before checking with virustotal is 20 min, this should be enough time for the honeypot to upload the binary and for virustotal to process it.   

Script output (if successful):
--Host script results:                                                                                                                                                               ---|_honeydetect: Binary detected by Virustotal, host most likely a Honeypot!

The script creates a file called hash.log, which contains the hostname of the host you scanned and the current hash. This can be useful if you scan multiple hosts or is the 20 min is not enough. This way you can manually check with VT afterwards. 

cat hash.log
localhost: 8ddf5b6c575cec55c5f1b1f8b984b178

The script searches for MD5 sums but VT presents the findings with a sha254 checksum.

sha256sum nping.exe
4753e5a9b8c1b53aa72cf45a193a8e4138099db84fcf33ac4b74d4e77e53321e  nping.exe

As you can see the file sent to the honeypot is the same as the one uploaded to VT
description = [[

Detect honeypots (like Dionaea) targeting the smb service and using Virustotal hash search for verification.
This is to be considered a PoC of a method of mapping honeypots and not an attack against Dionaea itself.

The code below could for example be extended to target other services(like FTP, HTTP etc) and also split the honeypot file upload and the Virustotal hash search to speed up detection for larger address ranges

Detection of honeypots is a double edged sword, we rely on them to catch new vulnerabilities and malware targeting common used services. But the presence of a honeypot can be a sign of vigilant opponent and could be used against the organizations that hosts the honeypot.

Please see my blog: for more information.


--- Output
--Host script results:                                                                                                                                                               ---|_honeydetect: Binary detected by Virustotal, host most likely a Honeypot!

author = "Mikael Keri"
license = "Same as Nmap--See"
categories = {"default", "discovery", "safe"}

require 'http'
require 'stdnse'
require 'smb'

hostrule = function(host)
        return smb.get_port(host) ~= nil

--- Get your VirusTotal API key from the
 local VTAPI = "XXX"

--- Name of binary and path to it
local BIN = "XXX"

-- This just takes a binary of your choice and adds a random string at the end of the file, very low tech. The reason to use a "real" file was in case the honeypot uses PEID or similar to determine if the uploaded file really is a binary.
 local RANDY = (math.random(10, 99999))
 file = io.output(, "a+"))

action = function(host)

 name = stdnse.get_hostname(host)
-- Get the Hash of the binary
-- OSX change to "md5 -q"
local ET = ("md5sum " .. BIN)
local BINHASH = io.popen(ET .. "| awk {' print $1 '}"):read'*l'

-- Write the hash to file .. just in case Virustotal is not able to process it during the 20 min this script waits..or if you would like to scan larger nets. Remove the sleep part
-- and process the hash.log file afterwards.
local hashf = io.output("hash.log", "a"))
   io.write(name ..": " .. BINHASH .."\n")

--- Upload the file to the "honeypot"
    local UPLOAD = ("smbclient //localhost/test -N -c='put " .. BIN .. "'
>/dev/null 2>&1")

--- Give the honeypot a chance to upload the file to .. sleep 20 min

--- Check with Virustotal to see what they say..
     local headers = {["Content-Type"] = "application/x-www-form-urlencoded"}
     local postdata = "resource=" .. BINHASH .. "&apikey=" .. VTAPI .. ""
     local body ="", 443, "/vtapi/v2/file/report", {["header"]=headers}, nil, postdata).body

     if string.find(body, 'response_code": 0') then
            return "Binary not uploaded to Virustotal"
         elseif string.find(body, 'response_code": 1') then
            return "Binary detected by Virustotal, host most likely a Honeypot!"



This area of research is quite fascinating so I'm looking forward to comment or future research ideas.

Thanks to @nevdull77 for his help!

Update: fixed a syntax error in the script