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
(http://aide.sourceforge.net/). 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 ---
#!/bin/sh
# 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>"
}
image_name=""
mount_dir=""
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"
usage
exit 1
;;
?) echo "Error: unknown option: $options"
usage
exit 1
;;
esac
done
if [ -z "$image_name" ]; then
echo "No image defined"
usage
exit 1if [ -z "$mount_dir" ]; then
echo "No mount directory defined"
usage
exit 1
fi
if [ -z "$aide" ]; then
echo "No Aide command defined - valid values are check or update"
usage
exit 1
fi
if [ $aide != "update" -a $aide != "check" ]; then
echo "Valid Aide arguments are either update or check"
usage
exit 1
fi
# remove trailing slash
mount_dir="${mount_dir%/}"
# only load the module once
if [ -z "$(lsmod | grep nbd)" ]; then
echo -n "Loading kernel module.."
modprobe nbd
sleep 5
echo "finished!"
fi
# 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/aide.db.new /usr/local/etc/aide.db
echo "finished!"
fi
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/aide.db.new /usr/local/etc/aide.db
echo "finished!"
fi
# umount and unload
echo -n "Cleaning.."
umount "$mount_dir"
qemu-nbd -d /dev/nbd0
echo "finished!"
fi
--- script end ---
Example syntax: ./hash_vm.sh -i /var/lib/libvirt/images/johndoe.qcow2 -m /mnt -a check
/Micke @nsmfoo
Network security with a twist of Incident Response tidbits and other IT-security related topics.
Thursday, October 18, 2012
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 copy HKLM\HARDWARE\ACPI\DSDT\VBOX__ HKLM\HARDWARE\ACPI\DSDT\WOOT__ /s /f
@reg delete HKLM\HARDWARE\ACPI\DSDT\VBOX__ /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\VBOXBIOS HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\WOOTBIOS /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\VBOXBIOS /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\<VENDOR>\VBOXFACP HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\<VENDOR>\WOOTFACP /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\<VENDOR>\VBOXFACP /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\<VENDOR>\VBOXRSDT HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\<VENDOR>\WOOTRSDT /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\<VENDOR>\VBOXRSDT /f
@reg add HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System /v VideoBiosVersion /t REG_MULTI_SZ /d "VGA BIOS v1.14" /f
---- end of script ---
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 copy HKLM\HARDWARE\ACPI\DSDT\VBOX__ HKLM\HARDWARE\ACPI\DSDT\WOOT__ /s /f
@reg delete HKLM\HARDWARE\ACPI\DSDT\VBOX__ /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\VBOXBIOS HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\WOOTBIOS /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\VBOXBIOS /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\<VENDOR>\VBOXFACP HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\<VENDOR>\WOOTFACP /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\<VENDOR>\VBOXFACP /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\<VENDOR>\VBOXRSDT HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\<VENDOR>\WOOTRSDT /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\<VENDOR>\VBOXRSDT /f
@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'/>
</interface>
* 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.
<os>
<smbios mode='sysinfo'/>
...
</os>
<sysinfo type='smbios'>
<bios>
<entry name='vendor'>XXXX</entry>
<entry name='version'>XXXXXX</entry>
<entry name='date'>XXXXX</entry>
<entry name='release'>XXXXX</entry>
</bios>
<system>
<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>
</system>
</sysinfo>
* 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:
https://lists.gnu.org/archive/html/qemu-devel/2012-03/msg02272.html.
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 copy HKLM\HARDWARE\ACPI\DSDT\BXPC HKLM\HARDWARE\ACPI\DSDT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\DSDT\BXPC /f
@reg copy HKLM\HARDWARE\ACPI\DSDT\WOOT\BXDSDT HKLM\HARDWARE\ACPI\DSDT\WOOT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\DSDT\WOOT\BXDSDT /f
@reg copy HKLM\HARDWARE\ACPI\FADT\BOCHS_ HKLM\HARDWARE\ACPI\FADT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\FADT\BOCHS_ /f
@reg copy HKLM\HARDWARE\ACPI\FADT\WOOT\BXPCFACP HKLM\HARDWARE\ACPI\FADT\WOOT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\FADT\WOOT\BXPCFACP /f
@reg copy HKLM\HARDWARE\ACPI\RSDT\BOCHS_ HKLM\HARDWARE\ACPI\RSDT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\RSDT\BOCHS_ /f
@reg copy HKLM\HARDWARE\ACPI\RSDT\WOOT\BXPCRSDT HKLM\HARDWARE\ACPI\RSDT\WOOT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\RSDT\WOOT\BXPCRSDT /f
@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://git.seabios.org/seabios.git
Edit the following file:
seabios/src/config.h
Locate the following part:
#define CONFIG_APPNAME "Bochs"
#define CONFIG_CPUNAME8 "BOCHSCPU"
#define CONFIG_APPNAME6 "BOCHS "
#define CONFIG_APPNAME4 "BXPC"
And change it to something appropriate
#define CONFIG_APPNAME "DELL"
#define CONFIG_CPUNAME8 "DELLCPU"
#define CONFIG_APPNAME6 "DELL "
#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"(?)
/Micke
@nsmfoo
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'/>
</interface>
* 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.
<os>
<smbios mode='sysinfo'/>
...
</os>
<sysinfo type='smbios'>
<bios>
<entry name='vendor'>XXXX</entry>
<entry name='version'>XXXXXX</entry>
<entry name='date'>XXXXX</entry>
<entry name='release'>XXXXX</entry>
</bios>
<system>
<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>
</system>
</sysinfo>
* 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:
https://lists.gnu.org/archive/html/qemu-devel/2012-03/msg02272.html.
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 copy HKLM\HARDWARE\ACPI\DSDT\BXPC HKLM\HARDWARE\ACPI\DSDT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\DSDT\BXPC /f
@reg copy HKLM\HARDWARE\ACPI\DSDT\WOOT\BXDSDT HKLM\HARDWARE\ACPI\DSDT\WOOT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\DSDT\WOOT\BXDSDT /f
@reg copy HKLM\HARDWARE\ACPI\FADT\BOCHS_ HKLM\HARDWARE\ACPI\FADT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\FADT\BOCHS_ /f
@reg copy HKLM\HARDWARE\ACPI\FADT\WOOT\BXPCFACP HKLM\HARDWARE\ACPI\FADT\WOOT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\FADT\WOOT\BXPCFACP /f
@reg copy HKLM\HARDWARE\ACPI\RSDT\BOCHS_ HKLM\HARDWARE\ACPI\RSDT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\RSDT\BOCHS_ /f
@reg copy HKLM\HARDWARE\ACPI\RSDT\WOOT\BXPCRSDT HKLM\HARDWARE\ACPI\RSDT\WOOT\WOOT /s /f
@reg delete HKLM\HARDWARE\ACPI\RSDT\WOOT\BXPCRSDT /f
@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://git.seabios.org/seabios.git
Edit the following file:
seabios/src/config.h
Locate the following part:
#define CONFIG_APPNAME "Bochs"
#define CONFIG_CPUNAME8 "BOCHSCPU"
#define CONFIG_APPNAME6 "BOCHS "
#define CONFIG_APPNAME4 "BXPC"
And change it to something appropriate
#define CONFIG_APPNAME "DELL"
#define CONFIG_CPUNAME8 "DELLCPU"
#define CONFIG_APPNAME6 "DELL "
#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"(?)
/Micke
@nsmfoo
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:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\IDE\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\IDE\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Enum\IDE\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Enum\IDE\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\IDE\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\IDE\
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:
https://itsultra.wordpress.com/2011/12/07/how-to-play-maplestory-using-virtualbox-4-1-x/
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 ---
@reg copy HKLM\HARDWARE\ACPI\DSDT\VBOX__ HKLM\HARDWARE\ACPI\DSDT\WOOT__ /s /f
@reg delete HKLM\HARDWARE\ACPI\DSDT\VBOX__ /f
@reg copy HKLM\HARDWARE\ACPI\RSDT\VBOX__ HKLM\HARDWARE\ACPI\RSDT\WOOT__ /s /f
@reg delete HKLM\HARDWARE\ACPI\RSDT\VBOX__ /f
@reg copy HKLM\HARDWARE\ACPI\FADT\VBOX__ HKLM\HARDWARE\ACPI\FADT\WOOT__ /s /f
@reg delete HKLM\HARDWARE\ACPI\FADT\VBOX__ /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\VBOXBIOS
HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\WOOTBIOS /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\VBOXBIOS /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\WOOT__\VBOXFACP
HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\WOOT__\WOOTFACP /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\WOOT__\VBOXFACP /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\WOOT__\VBOXRSDT
HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\WOOT__\WOOTRSDT /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\WOOT__\VBOXRSDT /f
@reg add HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System /v
SystemBiosVersion /t REG_MULTI_SZ /d "WOOT -1" /f
@reg add HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System /v
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
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:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\IDE\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\IDE\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Enum\IDE\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Enum\IDE\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\IDE\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\IDE\
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:
https://itsultra.wordpress.com/2011/12/07/how-to-play-maplestory-using-virtualbox-4-1-x/
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 ---
@reg copy HKLM\HARDWARE\ACPI\DSDT\VBOX__ HKLM\HARDWARE\ACPI\DSDT\WOOT__ /s /f
@reg delete HKLM\HARDWARE\ACPI\DSDT\VBOX__ /f
@reg copy HKLM\HARDWARE\ACPI\RSDT\VBOX__ HKLM\HARDWARE\ACPI\RSDT\WOOT__ /s /f
@reg delete HKLM\HARDWARE\ACPI\RSDT\VBOX__ /f
@reg copy HKLM\HARDWARE\ACPI\FADT\VBOX__ HKLM\HARDWARE\ACPI\FADT\WOOT__ /s /f
@reg delete HKLM\HARDWARE\ACPI\FADT\VBOX__ /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\VBOXBIOS
HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\WOOTBIOS /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\WOOT__\VBOXBIOS /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\WOOT__\VBOXFACP
HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\WOOT__\WOOTFACP /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\WOOT__\VBOXFACP /f
@reg copy HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\WOOT__\VBOXRSDT
HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\WOOT__\WOOTRSDT /s /f
@reg delete HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\WOOT__\VBOXRSDT /f
@reg add HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System /v
SystemBiosVersion /t REG_MULTI_SZ /d "WOOT -1" /f
@reg add HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System /v
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
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>"
Also:
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/piix3ide/0/Config/PrimaryMaster/FirmwareRevision" "<firmware>"
VBoxManage setextradata "<vm name>" "VBoxInternal/Devices/piix3ide/0/Config/PrimaryMaster/ModelNumber" "<model>"
/Micke
Update1:
Untested but might be useful..
VBoxManage setextradata "VM name" "VBoxInternal/TM/TSCTiedToExecution" 1
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>
- 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">
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>"
Also:
- Change MAC address:
- Change disk settings:
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!
/Micke
Update1:
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.
/Micke
# vtupload.pl
#!/usr/bin/perl
# This script is heavily based (to say the least) on the work done by cfrenz (http://perlgems.blogspot.se/2012/05/using-virustotal-api-v20.html My aim was to add some functionality to the original script.
# Usage: vtupload.pl <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='https://www.virustotal.com/vtapi/v2/file/scan';
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
$url='https://www.virustotal.com/vtapi/v2/file/report';
$response = $ua->post( $url,
['apikey' => $key,
'resource' => $sha256]
);
die "$url error: ", $response->status_line
unless $response->is_success;
$results=$response->content;
$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";
/Micke
# vtupload.pl
#!/usr/bin/perl
# This script is heavily based (to say the least) on the work done by cfrenz (http://perlgems.blogspot.se/2012/05/using-virustotal-api-v20.html My aim was to add some functionality to the original script.
# Usage: vtupload.pl <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='https://www.virustotal.com/vtapi/v2/file/scan';
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
$url='https://www.virustotal.com/vtapi/v2/file/report';
$response = $ua->post( $url,
['apikey' => $key,
'resource' => $sha256]
);
die "$url error: ", $response->status_line
unless $response->is_success;
$results=$response->content;
$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
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”
/Micke
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.
Result:
* 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: http://t.co/KRfPGQHh.
Tested services:
- vscan.novirusthanks.org
- vurldissect.co.uk
- onlinelinkscan.com
- zulu.zscaler.com/ (zscaler.com)
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
- www.unmaskparasites.com
- Webpawet
- URLQUERY.net
- Sucuri
or via google
"googlebot"
- aceinsight.websense.com (Websense)
- Bluecoat
- gred.jp
- Trend Micro
- Misc
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)
/Micke
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.
Result:
* 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: http://t.co/KRfPGQHh.
Tested services:
- vscan.novirusthanks.org
- IP: static
- User agent: "-"
- Note: Seems specialized to scan a direct file and not a whole "site" ..
- vurldissect.co.uk
- 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 "http://vurldissect.co.uk" in the referrer field.
- IP: static (registered to Comodo)
- User agent:
- onlinelinkscan.com
- IP: static
- User agent: "-"
- IP: Somewhat static (registered to Google)
- User agent:
- 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.
- zulu.zscaler.com/ (zscaler.com)
- IP: Multiple (one registered to zscaler.com) - but the IP addresses are static
- User agent:
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
- www.unmaskparasites.com
- IP: uses Google services
- User agent:
- Note: The appID is yet again a give away.
- Webpawet
- IP: Random /24 address registered to the University that hosts the solution
- User agent:
- Note: You are able to set not only referer but also headers
- URLQUERY.net
- IP: static and registered to a security company
- User agent:
- 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:
or via google
"googlebot"
- Note: The referrer field includes the name of the scanning service used.
- aceinsight.websense.com (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:
- Bluecoat
- IP: static (static net) Registered to Bluecoat
- User agent:
- gred.jp
- IP: Static IP
- User agent:
- 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:
- 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)
/Micke
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)
/Micke
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)
/Micke
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: blog.prowling.nu 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 http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "safe"}
require 'http'
require 'stdnse'
require 'smb'
hostrule = function(host)
return smb.get_port(host) ~= nil
end
--- Get your VirusTotal API key from the virustotal.com
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.
math.randomseed(os.time())
local RANDY = (math.random(10, 99999))
file = io.output(io.open(BIN, "a+"))
io.write(RANDY)
io.close(file)
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(io.open("hash.log", "a"))
io.write(name ..": " .. BINHASH .."\n")
io.close(hashf)
--- Upload the file to the "honeypot"
local UPLOAD = ("smbclient //localhost/test -N -c='put " .. BIN .. "' >/dev/null 2>&1")
os.execute(UPLOAD)
--- Give the honeypot a chance to upload the file to Virustotal.com .. sleep 20 min
stdnse.sleep(1200)
--- 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 = http.post("www.virustotal.com", 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!"
end
end
-------------
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
/Micke
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: blog.prowling.nu 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 http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "safe"}
require 'http'
require 'stdnse'
require 'smb'
hostrule = function(host)
return smb.get_port(host) ~= nil
end
--- Get your VirusTotal API key from the virustotal.com
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.
math.randomseed(os.time())
local RANDY = (math.random(10, 99999))
file = io.output(io.open(BIN, "a+"))
io.write(RANDY)
io.close(file)
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(io.open("hash.log", "a"))
io.write(name ..": " .. BINHASH .."\n")
io.close(hashf)
--- Upload the file to the "honeypot"
local UPLOAD = ("smbclient //localhost/test -N -c='put " .. BIN .. "' >/dev/null 2>&1")
os.execute(UPLOAD)
--- Give the honeypot a chance to upload the file to Virustotal.com .. sleep 20 min
stdnse.sleep(1200)
--- 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 = http.post("www.virustotal.com", 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!"
end
end
-------------
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
/Micke
Subscribe to:
Posts (Atom)