15 |
Static Analysis
16 | {% include "htmlSections/office.html" %}
17 | {% include "htmlSections/rtf.html" %}
18 | {% include "htmlSections/pdf.html" %}
19 | {% include "htmlSections/subfile.html" %}
20 | {% include "htmlSections/pe.html" %}
21 | {% include "htmlSections/network_analysis.html" %}
22 | {% include "htmlSections/other.html" %}
23 | {% endblock %}
--------------------------------------------------------------------------------
/src/data/index_result.yar:
--------------------------------------------------------------------------------
1 | include "yara_signatures/result_blackListLanguages.yar"
2 | include "yara_signatures/result_apihttp.yar"
--------------------------------------------------------------------------------
/src/data/index_sample.yar:
--------------------------------------------------------------------------------
1 | include "yara_signatures/sample_capabilities.yar"
2 | include "yara_signatures/sample_embedded.yar"
3 | include "yara_signatures/sample_kins.yar"
4 | include "yara_signatures/sample_njRAT.yar"
5 | include "yara_signatures/sample_vmdetect.yar"
6 | include "yara_signatures/sample_blackliststrings.yar"
7 | include "yara_signatures/sample_blackListFunctions.yar"
8 | include "yara_signatures/sample_maldoc.yara"
--------------------------------------------------------------------------------
/src/data/peiddb.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/data/peiddb.txt
--------------------------------------------------------------------------------
/src/data/yara_signatures/result_apihttp.yar:
--------------------------------------------------------------------------------
1 | rule HTTPApiFunctions {
2 | meta:
3 | description = "Uses the HTTP protocol functions"
4 | strings:
5 | $api1 = "HttpSendRequest" nocase
6 | $api2 = "HttpSendRequestEx" nocase
7 | $api3 = "HttpQueryInfo" nocase
8 | $api4 = "HttpAddRequestHeaders" nocase
9 | $api5 = "HttpEndRequest" nocase
10 | $api6 = "HttpOpenRequest" nocase
11 | condition:
12 | any of them
13 | }
--------------------------------------------------------------------------------
/src/data/yara_signatures/result_blackListLanguages.yar:
--------------------------------------------------------------------------------
1 | rule BlackListLanguages {
2 | meta:
3 | description = "Unconventionial binary language"
4 | strings:
5 | $lang1 = "LANG_ARABIC"
6 | $lang2 = "LANG_BULGARIAN"
7 | $lang3 = "LANG_CHINESE"
8 | $lang4 = "LANG_ROMANIAN"
9 | $lang5 = "LANG_RUSSIAN"
10 | $lang6 = "LANG_CROATO-SERBIAN"
11 | $lang7 = "LANG_SLOVAK"
12 | $lang8 = "LANG_ALBANIAN"
13 | $lang9 = "LANG_TURKISH"
14 | $lang10 = "LANG_HEBREW"
15 | $lang11 = "LANG_KOREAN"
16 | $lang12 = "SUBLANG_ENGLISH_JAMAICA"
17 | $lang13 = "SUBLANG_ENGLISH_CARIBBEAN"
18 | $lang14 = "SUBLANG_ENGLISH_BELIZE"
19 | $lang15 = "SUBLANG_ENGLISH_TRINIDAD"
20 | $lang16 = "SUBLANG_ENGLISH_ZIMBABWE"
21 | $lang17 = "SUBLANG_ENGLISH_PHILIPPINES"
22 | $lang18 = "LANG_UZBEK"
23 | $lang19 = "LANG_VIETNAMESE"
24 | $lang20 = "LANG_UKRAINIAN"
25 | $lang21 = "LANG_TELUGU"
26 | $lang22 = "LANG_SYRIAC"
27 | $lang23 = "LANG_SERBIAN"
28 | $lang24 = "LANG_LATVIAN"
29 | condition:
30 | any of them
31 | }
--------------------------------------------------------------------------------
/src/data/yara_signatures/sample_embedded.yar:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2010-2014 Cuckoo Foundation.
2 | // This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
3 | // See the file 'docs/LICENSE' for copying permission.
4 |
5 | rule embedded_macho
6 | {
7 | meta:
8 | author = "nex"
9 | description = "Contains an embedded Mach-O file"
10 |
11 | strings:
12 | $magic1 = { ca fe ba be }
13 | $magic2 = { ce fa ed fe }
14 | $magic3 = { fe ed fa ce }
15 | condition:
16 | any of ($magic*) and not ($magic1 at 0) and not ($magic2 at 0) and not ($magic3 at 0)
17 | }
18 |
19 | rule embedded_pe
20 | {
21 | meta:
22 | author = "nex"
23 | description = "Contains an embedded PE32 file"
24 |
25 | strings:
26 | $a = "PE32"
27 | $b = "This program"
28 | $mz = { 4d 5a }
29 | condition:
30 | ($a or $b) and not ($mz at 0)
31 | }
32 |
33 | rule embedded_win_api
34 | {
35 | meta:
36 | author = "nex"
37 | description = "A non-Windows executable contains win32 API functions names"
38 |
39 | strings:
40 | $mz = { 4d 5a }
41 | $api1 = "CreateFileA"
42 | $api2 = "GetProcAddress"
43 | $api3 = "LoadLibraryA"
44 | $api4 = "WinExec"
45 | $api5 = "GetSystemDirectoryA"
46 | $api6 = "WriteFile"
47 | $api7 = "ShellExecute"
48 | $api8 = "GetWindowsDirectory"
49 | $api9 = "URLDownloadToFile"
50 | $api10 = "IsBadReadPtr"
51 | $api11 = "IsBadWritePtr"
52 | $api12 = "SetFilePointer"
53 | $api13 = "GetTempPath"
54 | $api14 = "GetWindowsDirectory"
55 | condition:
56 | not ($mz at 0) and any of ($api*)
57 | }
58 |
--------------------------------------------------------------------------------
/src/data/yara_signatures/sample_kins.yar:
--------------------------------------------------------------------------------
1 |
2 | rule KINS_dropper {
3 | meta:
4 | author = "AlienVault Labs aortega@alienvault.com"
5 | description = "Match protocol, process injects and windows exploit present in KINS dropper"
6 | strings:
7 | // Network protocol
8 | $n1 = "tid=%d&ta=%s-%x" fullword
9 | $n2 = "fid=%d" fullword
10 | $n3 = "%[^.].%[^(](%[^)])" fullword
11 | // Injects
12 | $i0 = "%s [%s %d] 77 %s"
13 | $i01 = "Global\\%s%x"
14 | $i1 = "Inject::InjectProcessByName()"
15 | $i2 = "Inject::CopyImageToProcess()"
16 | $i3 = "Inject::InjectProcess()"
17 | $i4 = "Inject::InjectImageToProcess()"
18 | $i5 = "Drop::InjectStartThread()"
19 | // UAC bypass
20 | $uac1 = "ExploitMS10_092"
21 | $uac2 = "\\globalroot\\systemroot\\system32\\tasks\\" ascii wide
22 | $uac3 = "
HighestAvailable" ascii wide
23 | condition:
24 | 2 of ($n*) and 2 of ($i*) and 2 of ($uac*)
25 | }
26 |
27 | rule KINS_DLL_zeus {
28 | meta:
29 | author = "AlienVault Labs aortega@alienvault.com"
30 | description = "Match default bot in KINS leaked dropper, Zeus"
31 | strings:
32 | // Network protocol
33 | $n1 = "%BOTID%" fullword
34 | $n2 = "%opensocks%" fullword
35 | $n3 = "%openvnc%" fullword
36 | $n4 = /Global\\(s|v)_ev/ fullword
37 | // Crypted strings
38 | $s1 = "\x72\x6E\x6D\x2C\x36\x7D\x76\x77"
39 | $s2 = "\x18\x04\x0F\x12\x16\x0A\x1E\x08\x5B\x11\x0F\x13"
40 | $s3 = "\x39\x1F\x01\x07\x15\x19\x1A\x33\x19\x0D\x1F"
41 | $s4 = "\x62\x6F\x71\x78\x63\x61\x7F\x69\x2D\x67\x79\x65"
42 | $s5 = "\x6F\x69\x7F\x6B\x61\x53\x6A\x7C\x73\x6F\x71"
43 | condition:
44 | all of ($n*) and 1 of ($s*)
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/src/data/yara_signatures/sample_njRAT.yar:
--------------------------------------------------------------------------------
1 | rule win_exe_njRAT
2 | {
3 | meta:
4 | author = "info@fidelissecurity.com"
5 | descripion = "njRAT - Remote Access Trojan"
6 | comment = "Variants have also been observed obfuscated with .NET Reactor"
7 | filetype = "pe"
8 | date = "2013-07-15"
9 | version = "1.0"
10 | hash1 = "92ee1fb5df21d8cfafa2b02b6a25bd3b"
11 | hash2 = "3576d40ce18bb0349f9dfa42b8911c3a"
12 | hash3 = "24cc5b811a7f9591e7f2cb9a818be104"
13 | hash4 = "3ad5fded9d7fdf1c2f6102f4874b2d52"
14 | hash5 = "a98b4c99f64315aac9dd992593830f35"
15 | hash6 ="5fcb5282da1a2a0f053051c8da1686ef"
16 | hash7 = "a669c0da6309a930af16381b18ba2f9d"
17 | hash8 = "79dce17498e1997264346b162b09bde8"
18 | hash9 = "fc96a7e27b1d3dab715b2732d5c86f80"
19 | ref1 = "http://bit.ly/19tlf4s"
20 | ref2 = "http://www.fidelissecurity.com/threatadvisory"
21 | ref3 = "http://www.threatgeek.com/2013/06/fidelis-threat-advisory-1009-njratuncovered.html"
22 | ref4 = "http://threatgeek.typepad.com/files/fta-1009---njrat-uncovered.pdf"
23 |
24 | strings:
25 | $magic = "MZ"
26 | $string_setA_1 = "FromBase64String"
27 | $string_setA_2 = "Base64String"
28 | $string_setA_3 = "Connected" wide ascii
29 | $string_setA_4 = "Receive"
30 | $string_setA_5 = "DeleteSubKey" wide ascii
31 | $string_setA_6 = "get_MachineName"
32 | $string_setA_7 = "get_UserName"
33 | $string_setA_8 = "get_LastWriteTime"
34 | $string_setA_9 = "GetVolumeInformation"
35 |
36 | $string_setB_1 = "OSFullName" wide ascii
37 | $string_setB_2 = "Send" wide ascii
38 | $string_setB_3 = "Connected" wide ascii
39 | $string_setB_4 = "DownloadData" wide ascii
40 | $string_setB_5 = "netsh firewall" wide
41 | $string_setB_6 = "cmd.exe /k ping 0 & del" wide
42 |
43 | condition:
44 | ($magic at 0) and ( all of ($string_setA*) or all of ($string_setB*) )
45 | }
46 |
47 | rule network_traffic_njRAT
48 | {
49 | meta:
50 | author = "info@fidelissecurity.com"
51 | descripion = "njRAT - Remote Access Trojan"
52 | comment = "Rule to alert on network traffic indicators"
53 | filetype = "PCAP - Network Traffic"
54 | date = "2013-07-15"
55 | version = "1.0"
56 | hash1 = "92ee1fb5df21d8cfafa2b02b6a25bd3b"
57 | hash2 ="3576d40ce18bb0349f9dfa42b8911c3a"
58 | hash3 ="24cc5b811a7f9591e7f2cb9a818be104"
59 | hash4 = "3ad5fded9d7fdf1c2f6102f4874b2d52"
60 | hash5 = "a98b4c99f64315aac9dd992593830f35"
61 | hash6 = "5fcb5282da1a2a0f053051c8da1686ef"
62 | hash7 = "a669c0da6309a930af16381b18ba2f9d"
63 | hash8 = "79dce17498e1997264346b162b09bde8"
64 | hash9 = "fc96a7e27b1d3dab715b2732d5c86f80"
65 | ref1 = "http://bit.ly/19tlf4s"
66 | ref2 = "http://www.fidelissecurity.com/threatadvisory"
67 | ref3 = "http://www.threatgeek.com/2013/06/fidelis-threat-advisory-1009-njrat-uncovered.html"
68 | ref4 = "http://threatgeek.typepad.com/files/fta-1009---njrat-uncovered.pdf"
69 |
70 | strings:
71 | $string1 = "FM|'|'|" // File Manager
72 | $string2 = "nd|'|'|" // File Manager
73 | $string3 = "rn|'|'|" // Run File
74 | $string4 = "sc~|'|'|" // Remote Desktop
75 | $string5 = "scPK|'|'|" // Remote Desktop
76 | $string6 = "CAM|'|'|" // Remote Cam
77 | $string7 = "USB Video Device[endof]" // Remote Cam
78 | $string8 = "rs|'|'|" // Reverse Shell
79 | $string9 = "proc|'|'|" // Process Manager
80 | $string10 = "k|'|'|" // Process Manager
81 | $string11 = "RG|'|'|~|'|'|" // Registry Manipulation
82 | $string12 = "kl|'|'|" // Keylogger file
83 | $string13 = "ret|'|'|" // Get Browser Passwords
84 | $string14 = "pl|'|'|" // Get Browser Passwords
85 | $string15 = "lv|'|'|" // General
86 | $string16 = "prof|'|'|~|'|'|" // Server rename
87 | $string17 = "un|'|'|~[endof]" // Uninstall
88 | $idle_string = "P[endof]" // Idle Connection
89 |
90 | condition:
91 | any of ($string*) or #idle_string > 4
92 |
93 | }
--------------------------------------------------------------------------------
/src/data/yara_signatures/sample_vmdetect.yar:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2010-2014 Cuckoo Foundation.
2 | // This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
3 | // See the file 'docs/LICENSE' for copying permission.
4 |
5 | rule vmdetect
6 | {
7 | meta:
8 | author = "nex"
9 | description = "Possibly employs anti-virtualization techniques"
10 |
11 | strings:
12 | // Binary tricks
13 | $vmware = {56 4D 58 68}
14 | $virtualpc = {0F 3F 07 0B}
15 | $ssexy = {66 0F 70 ?? ?? 66 0F DB ?? ?? ?? ?? ?? 66 0F DB ?? ?? ?? ?? ?? 66 0F EF}
16 | $vmcheckdll = {45 C7 00 01}
17 | $redpill = {0F 01 0D 00 00 00 00 C3}
18 |
19 | // Random strings
20 | $vmware1 = "VMXh"
21 | $vmware2 = "Ven_VMware_" nocase
22 | $vmware3 = "Prod_VMware_Virtual_" nocase
23 | $vmware4 = "hgfs.sys" nocase
24 | $vmware5 = "mhgfs.sys" nocase
25 | $vmware6 = "prleth.sys" nocase
26 | $vmware7 = "prlfs.sys" nocase
27 | $vmware8 = "prlmouse.sys" nocase
28 | $vmware9 = "prlvideo.sys" nocase
29 | $vmware10 = "prl_pv32.sys" nocase
30 | $vmware11 = "vpc-s3.sys" nocase
31 | $vmware12 = "vmsrvc.sys" nocase
32 | $vmware13 = "vmx86.sys" nocase
33 | $vmware14 = "vmnet.sys" nocase
34 | $vmware15 = "vmicheartbeat" nocase
35 | $vmware16 = "vmicvss" nocase
36 | $vmware17 = "vmicshutdown" nocase
37 | $vmware18 = "vmicexchange" nocase
38 | $vmware19 = "vmdebug" nocase
39 | $vmware20 = "vmmouse" nocase
40 | $vmware21 = "vmtools" nocase
41 | $vmware22 = "VMMEMCTL" nocase
42 | $vmware23 = "vmx86" nocase
43 | $vmware24 = "vmware" nocase
44 | $virtualpc1 = "vpcbus" nocase
45 | $virtualpc2 = "vpc-s3" nocase
46 | $virtualpc3 = "vpcuhub" nocase
47 | $virtualpc4 = "msvmmouf" nocase
48 | $xen1 = "xenevtchn" nocase
49 | $xen2 = "xennet" nocase
50 | $xen3 = "xennet6" nocase
51 | $xen4 = "xensvc" nocase
52 | $xen5 = "xenvdb" nocase
53 | $xen6 = "XenVMM" nocase
54 | $virtualbox1 = "VBoxHook.dll" nocase
55 | $virtualbox2 = "VBoxService" nocase
56 | $virtualbox3 = "VBoxTray" nocase
57 | $virtualbox4 = "VBoxMouse" nocase
58 | $virtualbox5 = "VBoxGuest" nocase
59 | $virtualbox6 = "VBoxSF" nocase
60 | $virtualbox7 = "VBoxGuestAdditions" nocase
61 | $virtualbox8 = "VBOX HARDDISK" nocase
62 |
63 | // MAC addresses
64 | $vmware_mac_1a = "00-05-69"
65 | $vmware_mac_1b = "00:05:69"
66 | $vmware_mac_1c = "000569"
67 | $vmware_mac_2a = "00-50-56"
68 | $vmware_mac_2b = "00:50:56"
69 | $vmware_mac_2c = "005056"
70 | $vmware_mac_3a = "00-0C-29" nocase
71 | $vmware_mac_3b = "00:0C:29" nocase
72 | $vmware_mac_3c = "000C29" nocase
73 | $vmware_mac_4a = "00-1C-14" nocase
74 | $vmware_mac_4b = "00:1C:14" nocase
75 | $vmware_mac_4c = "001C14" nocase
76 | $virtualbox_mac_1a = "08-00-27"
77 | $virtualbox_mac_1b = "08:00:27"
78 | $virtualbox_mac_1c = "080027"
79 |
80 | $vm0 = "VIRTUAL HD" nocase
81 | $vm1 = "VMWARE VIRTUAL IDE HARD DRIVE" nocase
82 | $vm2 = "QEMU HARDDISK" nocase
83 | $vm3 = "VBOX HARDDRIVE" nocase
84 | $vm4 = "The Wireshark Network Analyzer"
85 | $vm7 = "Process Monitor - Sysinternals: www.sysinternals.com"
86 | $vm8 = "File Monitor - Sysinternals: www.sysinternals.com"
87 | $vm9 = "Registry Monitor - Sysinternals: www.sysinternals.com"
88 |
89 | condition:
90 | any of them
91 | }
92 |
--------------------------------------------------------------------------------
/src/dumpdir/files/empty.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/dumpdir/files/empty.txt
--------------------------------------------------------------------------------
/src/dumpdir/reports/empty.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/dumpdir/reports/empty.txt
--------------------------------------------------------------------------------
/src/preProcessing/01_unpack_archive.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | from os import walk
5 | from os.path import join
6 | import logging
7 | import shutil
8 | import tempfile
9 |
10 | from core.abstracts import Processing
11 | import core.commonutils as commonutils
12 |
13 |
14 | try:
15 | from yapsy.IPlugin import IPlugin
16 | except ImportError:
17 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
18 |
19 | log = logging.getLogger("UnpackArchive")
20 |
21 | class UnpackArchive(IPlugin, Processing):
22 |
23 | def run(self, objfile):
24 | tmpdir = tempfile.mkdtemp()
25 | tmp_files = []
26 |
27 | try:
28 | commonutils.unpackArchive(objfile.file.temp_file, tmpdir)
29 |
30 | for root, dirs, files in walk(tmpdir):
31 | for file in files:
32 | full_path = join(root, file)
33 | if not commonutils.isArchive(full_path):
34 | tmp_files.append(full_path)
35 |
36 | if len(tmp_files) == 1 and commonutils.isPermittedType(tmp_files[0]):
37 | # len == 1 > easy, replace archive file in objfile
38 | objfile.set_file_from_path(tmp_files[0])
39 | else:
40 | for file in tmp_files:
41 | if commonutils.isPermittedType(file):
42 | objfile.set_unpacked_file(file)
43 | finally:
44 | # Temp-Folder loeschen
45 | shutil.rmtree(tmpdir)
46 |
47 | return objfile
48 |
--------------------------------------------------------------------------------
/src/preProcessing/01_unpack_archive.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = 01_unpack_archive
3 | Module = 01_unpack_archive
4 |
5 | [Documentation]
6 | Description = Recurse unpack archive
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/preProcessing/02_unpacker_clamav.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import re
7 | import shutil
8 | import subprocess
9 |
10 | from core.abstracts import Processing
11 | from core.constants import RAGPICKER_ROOT
12 |
13 |
14 | try:
15 | from yapsy.IPlugin import IPlugin
16 | except ImportError:
17 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
18 |
19 | log = logging.getLogger("ClamAvUnpacker")
20 |
21 | class ClamAvUnpacker(IPlugin, Processing):
22 | """ Supported packer: Aspack, UPX, FSG, Petite, PeSpin, NsPack, wwpack32, Mew, Upack, Yoda Cryptor
23 | """
24 | def run(self, objfile):
25 | self.avPath = self.options.get("clamscan_path", None)
26 | tmpPath = self.getTmpPath('clamscan_')
27 |
28 | try:
29 | self._unpack(objfile, tmpPath)
30 | except (Exception) as e:
31 | log.error("The module \"ClamAvUnpacker\" returned the following error: %s" % e)
32 | finally:
33 | # Delete tmpPath
34 | shutil.rmtree(tmpPath, ignore_errors=True)
35 |
36 | return objfile
37 |
38 | def _unpack(self, objfile, temp_path):
39 | if not self.avPath:
40 | raise Exception("ClamAv path is not set in the configuration!")
41 |
42 | if os.path.isfile(self.avPath):
43 | try:
44 | dummyDB = os.path.join(RAGPICKER_ROOT, 'data', 'clamav_dummy.hdb')
45 | output = subprocess.Popen([self.avPath, "--debug", "--leave-temps", "--database=" + dummyDB, \
46 | "--tempdir=" + temp_path, objfile.file.temp_file], \
47 | stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
48 |
49 | # FSG: Unpacked and rebuilt executable saved in
50 | # UPX/FSG: Decompressed data saved in
51 | # MEW: Unpacked and rebuilt executable saved in
52 | if " saved in " in output[0]:
53 | log.info("File unpacked !!!!")
54 | unpackedFile = self._parseUnpacked(output[0])
55 | objfile.set_unpacked_file(unpackedFile)
56 | except (Exception) as e:
57 | raise Exception("ClamAV _unpack file %s Failed" % e)
58 |
59 | def _parseUnpacked(self, data):
60 | rpd = re.compile('debug:.*saved\sin\s(.+)', re.IGNORECASE)
61 | rpdFind = re.findall(rpd, data)
62 |
63 | for file in rpdFind:
64 | log.debug(file)
65 | return file
66 |
--------------------------------------------------------------------------------
/src/preProcessing/02_unpacker_clamav.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = 02_unpacker_clamav
3 | Module = 02_unpacker_clamav
4 |
5 | [Documentation]
6 | Description = Unpacking with ClamAv AntiVirus (http://www.clamav.net/lang/en/)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/preProcessing/03_extract_rsrc.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 |
6 | from core.commonutils import getFileTypeFromBuffer
7 | from core.abstracts import Processing
8 | from utils.pefile import PE
9 | from utils.pefile import PEFormatError
10 |
11 | try:
12 | from yapsy.IPlugin import IPlugin
13 | except ImportError:
14 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
15 |
16 | log = logging.getLogger("ExtractRSRC")
17 |
18 | class ExtractRSRC(IPlugin, Processing):
19 |
20 | def run(self, objfile):
21 | self.extractTypes = self.options.get("extracttypes")
22 |
23 | try:
24 | pe = PE(data=objfile.file.file_data)
25 | resources = self.getResources(pe)
26 |
27 | if objfile.unpacked_file:
28 | pe = PE(data=objfile.unpacked_file.file_data)
29 | resources = resources + self.getResources(pe)
30 |
31 | for resource in resources:
32 | objfile.add_included_file(resource)
33 | except PEFormatError, e:
34 | log.warn("Error - No Portable Executable: %s" % e)
35 | except (Exception) as e:
36 | log.error("The module \"ExtractRSRC\" returned the following error: %s" % e)
37 | finally:
38 | pass
39 |
40 | return objfile
41 |
42 | def getResources(self, pe):
43 | ret = []
44 | if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
45 | for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
46 | if hasattr(resource_type, 'directory'):
47 | for resource_id in resource_type.directory.entries:
48 | if hasattr(resource_id, 'directory'):
49 | for resource_lang in resource_id.directory.entries:
50 | data = pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size)
51 | filetype = getFileTypeFromBuffer(data)
52 |
53 | log.debug("Found: " + filetype)
54 |
55 | if filetype in self.extractTypes:
56 | #TODO: RAR und ZIP entpacken!!!
57 | ret.append(data)
58 | log.info("Append File: " + filetype)
59 | return ret
60 |
--------------------------------------------------------------------------------
/src/preProcessing/03_extract_rsrc.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = 03_extract_rsrc
3 | Module = 03_extract_rsrc
4 |
5 | [Documentation]
6 | Description = Extract .rsrc-Section
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/preProcessing/04_extract_office.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import re
7 | import shutil
8 | import subprocess
9 |
10 | from core.abstracts import Processing
11 | from core.constants import RAGPICKER_ROOT
12 |
13 |
14 | try:
15 | from yapsy.IPlugin import IPlugin
16 | except ImportError:
17 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
18 |
19 | log = logging.getLogger("ExtractOffice")
20 |
21 | class ExtractOffice(IPlugin, Processing):
22 |
23 | def run(self, objfile):
24 | wine = self.options.get("wine", "/usr/bin/wine")
25 | brute = self.options.get("brute", True)
26 | tmpPath = self.getTmpPath("extractOffice_")
27 |
28 | try:
29 | officeFile = os.path.join(tmpPath, "temp.file")
30 | # Copy TempFile > new TempDir
31 | shutil.copyfile(objfile.file.temp_file, officeFile)
32 | scanner = None
33 | option = None
34 |
35 | if objfile.file.get_type() == "Composite":
36 | scanner = os.path.join(RAGPICKER_ROOT, 'utils', 'OfficeMalScanner', 'OfficeMalScanner.exe')
37 | option = "' scan"
38 | if brute:
39 | option = option + " brute"
40 | elif objfile.file.get_type() == "Rich":
41 | scanner = os.path.join(RAGPICKER_ROOT, 'utils', 'OfficeMalScanner', 'RTFScan.exe')
42 | option = "' scan"
43 |
44 | cmd = wine + " " + scanner + " '" + officeFile + option
45 | log.debug(cmd)
46 | self.officeScanExe(cmd, tmpPath, objfile)
47 |
48 | except (Exception) as e:
49 | log.error("The module \"ExtractOffice\" returned the following error: %s" % e)
50 | finally:
51 | # Delete tmpPath
52 | shutil.rmtree(tmpPath, ignore_errors=True)
53 |
54 | return objfile
55 |
56 | def officeScanExe(self, cmd, tmpPath, objfile):
57 | process = subprocess.Popen(cmd, stdout=subprocess.PIPE, cwd=tmpPath, shell=True)
58 | (stdout, stderr) = process.communicate()
59 |
60 | stdout = stdout.decode('utf-8', 'ignore')
61 |
62 | if stdout:
63 | if "unencrypted MZ/PE signature found" in stdout:
64 | log.info("MZ/PE File unpacked !!!!")
65 | unpackedFile = self._parseUnpacked(stdout)
66 | log.info("OLEScan = " + unpackedFile)
67 | objfile.set_unpacked_file(os.path.join(tmpPath, str(unpackedFile).strip()))
68 | else:
69 | raise Exception(stderr)
70 |
71 | def _parseUnpacked(self, data):
72 | rpd = re.compile('Dumping Memory to disk as filename:\s(.+)', re.IGNORECASE)
73 | rpdFind = re.findall(rpd, data)
74 |
75 | for file in rpdFind:
76 | log.debug(file)
77 | return file
78 |
--------------------------------------------------------------------------------
/src/preProcessing/04_extract_office.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = 04_extract_office
3 | Module = 04_extract_office
4 |
5 | [Documentation]
6 | Description = Extract PE-Files from Office-Documents
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/preProcessing/05_pe_carve.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import re
5 | import logging
6 | import utils.pefile as pefile
7 | from core.commonutils import getFileTypeFromBuffer
8 | from core.abstracts import Processing
9 |
10 |
11 |
12 | try:
13 | from yapsy.IPlugin import IPlugin
14 | except ImportError:
15 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
16 |
17 | log = logging.getLogger("PeCarve")
18 |
19 | class PeCarve(IPlugin, Processing):
20 |
21 | def run(self, objfile):
22 |
23 | try:
24 | objfile.file.temp_file
25 | carvedFiles = self.carve(objfile.file.temp_file)
26 |
27 | if objfile.unpacked_file:
28 | carvedFiles = carvedFiles + self.carve(objfile.unpacked_file.temp_file)
29 |
30 | for carvedFile in carvedFiles:
31 | objfile.add_included_file(carvedFile)
32 | # except (Exception) as e:
33 | # log.error("The module \"PeCarve\" returned the following error: %s" % e)
34 | finally:
35 | pass
36 |
37 | return objfile
38 |
39 | def carve(self, filePath):
40 | cavedFiles = []
41 | # read the file into a buffer
42 | try:
43 | file = open(filePath, 'rb')
44 | buffer = file.read()
45 | except (Exception) as e:
46 | raise Exception("PeCarve could not access file: %s" % filePath)
47 |
48 | # carve out embeddded executables
49 | # For each address that contains MZ
50 | for offset in [tmp.start() for tmp in re.finditer('\x4d\x5a', buffer)]:
51 | file.seek(offset)
52 |
53 | # MZ on offset 0x0
54 | if offset == 0:
55 | continue
56 |
57 | try:
58 | pe = pefile.PE(data=file.read())
59 | except:
60 | # Failed to parse EXE
61 | continue
62 |
63 | log.info('PE found at offset: ' + hex(offset))
64 | cavedFiles.append(pe.trim())
65 |
66 | file.seek(0)
67 | pe.close()
68 |
69 | return cavedFiles
--------------------------------------------------------------------------------
/src/preProcessing/05_pe_carve.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = 05_pe_carve
3 | Module = 05_pe_carve
4 |
5 | [Documentation]
6 | Description = Carve out embeddded executables
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/preProcessing/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/preProcessing/__init__.py
--------------------------------------------------------------------------------
/src/processing/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/processing/all_bluecoatMalwareAnalysisAppliance.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = all_bluecoatMalwareAnalysisAppliance
3 | Module = all_bluecoatMalwareAnalysisAppliance
4 |
5 | [Documentation]
6 | Description = Adds the Sample to Blue Coat Malware Analysis Appliance (https://www.bluecoat.com)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
9 | Website = https://www.bluecoat.com/products/malware-analysis-appliance
--------------------------------------------------------------------------------
/src/processing/all_cuckooSandbox.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import json
5 | import logging
6 | import urllib2
7 |
8 | from core.abstracts import Processing
9 | from utils.multiPartForm import MultiPartForm
10 |
11 |
12 | try:
13 | from yapsy.IPlugin import IPlugin
14 | except ImportError:
15 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
16 |
17 | log = logging.getLogger("ProcessingCuckooSandbox")
18 |
19 | CUCKOO_TASK_CREATE_URL = "http://%s:%s/tasks/create/file "
20 |
21 | class CuckooSandbox(IPlugin, Processing):
22 |
23 | def run(self, objfile):
24 | self.key = "CuckooSandbox"
25 | self.score = -1
26 | self.host = self.options.get("host")
27 | self.port = self.options.get("port")
28 | reponsejson = {}
29 |
30 | if not self.host or not self.port:
31 | raise Exception("Cuckoo REST API server not configurated")
32 |
33 | file_extension = '.' + objfile.file.file_extension()
34 | fileName = objfile.file.get_fileMd5() + file_extension
35 | rawFile = open(objfile.file.temp_file, 'rb')
36 |
37 | log.debug(CUCKOO_TASK_CREATE_URL % (self.host, self.port) + " file=" + fileName)
38 |
39 | try:
40 | form = MultiPartForm()
41 | form.add_file('file', fileName, fileHandle=rawFile)
42 |
43 | request = urllib2.Request(CUCKOO_TASK_CREATE_URL % (self.host, self.port))
44 | request.add_header('User-agent', 'Ragpicker')
45 | body = str(form)
46 | request.add_header('Content-type', form.get_content_type())
47 | request.add_header('Content-length', len(body))
48 | request.add_data(body)
49 |
50 | data = urllib2.urlopen(request, timeout=60).read()
51 | reponsejson = json.loads(data)
52 | log.info("Submitted to cuckoo, task ID %s", reponsejson["task_id"])
53 | except urllib2.URLError as e:
54 | raise Exception("Unable to establish connection to Cuckoo REST API server: %s" % e)
55 | except urllib2.HTTPError as e:
56 | raise Exception("Unable to perform HTTP request to Cuckoo REST API server (http code=%s)" % e)
57 | except ValueError as e:
58 | raise Exception("Unable to convert response to JSON: %s" % e)
59 |
60 | return reponsejson
61 |
--------------------------------------------------------------------------------
/src/processing/all_cuckooSandbox.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = all_cuckooSandbox
3 | Module = all_cuckooSandbox
4 |
5 | [Documentation]
6 | Description = Adds the Sample to the list of cuckoo-sandbox tasks to be processed and analyzed
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
9 | Website =
--------------------------------------------------------------------------------
/src/processing/all_info.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = all_info
3 | Module = all_info
4 |
5 | [Documentation]
6 | Description = Sample Base Infos (Don't disable "info"-Module!!!)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
9 | Website =
--------------------------------------------------------------------------------
/src/processing/all_subFile.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import StringIO
5 | import logging
6 | import re
7 | import sys
8 |
9 | from core.abstracts import Processing
10 |
11 |
12 | try:
13 | from hachoir_subfile.search import SearchSubfile
14 | from hachoir_core.stream import FileInputStream
15 | from hachoir_core.cmd_line import unicodeFilename
16 | except ImportError:
17 | raise ImportError, 'hachoir-subfile is required to run this program : http://bitbucket.org/haypo/hachoir/wiki/hachoir-subfile'
18 |
19 | try:
20 | from yapsy.IPlugin import IPlugin
21 | except ImportError:
22 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
23 |
24 | log = logging.getLogger("ProcessingSubFile")
25 |
26 | class subFile(IPlugin, Processing):
27 |
28 | def run(self, objfile):
29 | self.key = "SubFile"
30 | self.score = -1
31 | # Dictionary containing all the results of this processing.
32 | results = {}
33 |
34 | try:
35 | results = self.subfile(objfile.file.temp_file)
36 | except (Exception) as e:
37 | log.error("The module \"SubFile\" returned the following error: %s" % e)
38 |
39 | return results
40 |
41 | def subfile(self, filePath):
42 | # hachoir-subfile is a tool based on hachoir-parser to find subfiles in any binary stream.
43 | # Website: http://bitbucket.org/haypo/hachoir/wiki/hachoir-subfile
44 | # bypass sys.stdout, sys.stderr
45 | oldStdOut = sys.stdout
46 | oldStdErr = sys.stderr
47 | outputStdErr = StringIO.StringIO()
48 | outputStdOut = StringIO.StringIO()
49 | sys.stdout = outputStdOut
50 | sys.stderr = outputStdErr
51 |
52 | stream = FileInputStream(unicodeFilename(filePath), real_filename=filePath)
53 |
54 | # Search for subfiles
55 | subfile = SearchSubfile(stream, 0, None)
56 | subfile.loadParsers(categories=None, parser_ids=None)
57 | subfile.main()
58 |
59 | # sys.stdout, sys.stderr reset
60 | sys.stdout = oldStdOut
61 | sys.stderr = oldStdErr
62 |
63 | # parse stdout, stderr from SearchSubfile
64 | return self.parse(outputStdOut.getvalue(), outputStdErr.getvalue())
65 |
66 | def parse(self, stdout, stderr):
67 | results = {}
68 | if stderr:
69 | if not len(stderr.split('\n')) <= 1:
70 | ret = []
71 | line = stderr.split('\n')
72 | for l in line:
73 | if len(l) > 0: ret.append(l)
74 | results["Errors"] = ret
75 | if stdout:
76 | if not len(stdout.split('\n')) <= 2:
77 | ret = []
78 | line = stdout.split('\n')
79 | for l in line:
80 | if not re.findall('File at 0 size=', l):
81 | subfile = l.replace("[+] ", "").split(': ')
82 | if len(subfile) > 1:
83 | sFile = {}
84 | sFile["FileType"] = subfile[1]
85 | sFile["Desc"] = subfile[0]
86 | ret.append(sFile)
87 | results["Files"] = ret
88 |
89 | return results
90 |
--------------------------------------------------------------------------------
/src/processing/all_subFile.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = all_subFile
3 | Module = all_subFile
4 |
5 | [Documentation]
6 | Description = Find subfile in any binary stream
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
9 | Website =
--------------------------------------------------------------------------------
/src/processing/all_virustotal.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = all_virustotal
3 | Module = all_virustotal
4 |
5 | [Documentation]
6 | Description = Gets detection ratio from VirusTotal.com (via VT API)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
9 | Website =
--------------------------------------------------------------------------------
/src/processing/all_yara.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 |
6 | from core.abstracts import Processing
7 | import core.commonutils as commonutils
8 |
9 |
10 | try:
11 | from yapsy.IPlugin import IPlugin
12 | except ImportError:
13 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
14 |
15 | log = logging.getLogger("ProcessingYara")
16 |
17 | class Yara(IPlugin, Processing):
18 |
19 | def run(self, objfile):
20 | self.key = "Yara"
21 | self.score = 0
22 | rulepath = self.options.get("rulepath")
23 | results = []
24 | resultOrginalFile = commonutils.processYara(rulepath, filepath=objfile.file.temp_file)
25 |
26 | # Run YARA for unpacked file
27 | if objfile.unpacked_file:
28 | resultUnpackedFile = commonutils.processYara(rulepath, filepath=objfile.unpacked_file.temp_file,
29 | prefix="UnpackedFile")
30 |
31 | # Update Meta-description -> set marker UnpackedFile
32 | for res in resultUnpackedFile:
33 | desc = res.get("meta").get("description")
34 | desc = "UnpackedFile - %s" % desc
35 | res["meta"]["description"] = desc
36 | results.append(res)
37 |
38 | results = results + resultOrginalFile
39 |
40 | return results
41 |
--------------------------------------------------------------------------------
/src/processing/all_yara.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = all_yara
3 | Module = all_yara
4 |
5 | [Documentation]
6 | Description = Identify and classify malware with yara (http://plusvic.github.io/yara/)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/antivirus_avast.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import re
7 | import subprocess
8 |
9 | from core.abstracts import Processing
10 |
11 |
12 | try:
13 | from yapsy.IPlugin import IPlugin
14 | except ImportError:
15 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
16 |
17 | log = logging.getLogger("Processing avast Antivirus")
18 |
19 | class Avast(IPlugin, Processing):
20 |
21 | def run(self, objfile):
22 | self.key = "AntivirusScanAvast"
23 | self.score = 0
24 | self.avPath = self.options.get("avast_path", None)
25 | result = {}
26 |
27 | try:
28 | result["avast"] = self.avast(objfile.file.temp_file)
29 | except (Exception) as e:
30 | log.error("The module \"avast\" returned the following error: %s" % e)
31 |
32 | return result
33 |
34 | def avast(self, file_path):
35 | result = None
36 |
37 | if not self.avPath:
38 | raise Exception("avast Antivir path is not set in the configuration!")
39 |
40 | if os.path.isfile(self.avPath):
41 | try:
42 | output = subprocess.Popen([self.avPath, '-a', file_path], stdout=subprocess.PIPE).communicate()[0]
43 |
44 | if not "[OK]" in output:
45 | self.score = 10
46 | rpd = re.compile('\[infected by:\s(.+)]', re.IGNORECASE)
47 | rpdFind = re.findall(rpd, output)
48 |
49 | r = ''
50 | for r in rpdFind:
51 | result = r
52 | else:
53 | result = 'OK'
54 | except (Exception) as e:
55 | raise Exception("avast Antivir scan file '%s' Failed" % e)
56 |
57 | log.info(result)
58 |
59 | return result
60 |
--------------------------------------------------------------------------------
/src/processing/antivirus_avast.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = antivirus_avast
3 | Module = antivirus_avast
4 |
5 | [Documentation]
6 | Description = avast! Free Antivirus für Linux v1.3.0 (http://www.avast.com)
7 | Author = Mark Lawrenz
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/antivirus_avg.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import subprocess
7 |
8 | from core.abstracts import Processing
9 |
10 |
11 | try:
12 | from yapsy.IPlugin import IPlugin
13 | except ImportError:
14 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
15 |
16 | log = logging.getLogger("ProcessingAvgAv")
17 |
18 | class Avg(IPlugin, Processing):
19 |
20 | def run(self, objfile):
21 | self.key = "AntivirusScanAvg"
22 | self.score = 0
23 | self.avPath = self.options.get("avg_path", None)
24 | result = {}
25 |
26 | try:
27 | result["Avg"] = self.avg(objfile.file.temp_file)
28 | except (Exception) as e:
29 | log.error("The module \"Avg\" returned the following error: %s" % e)
30 |
31 | return result
32 |
33 | def avg(self, file_path):
34 | result = None
35 |
36 | if not self.avPath:
37 | raise Exception("AvgAV path is not set in the configuration!")
38 |
39 | if os.path.isfile(self.avPath):
40 | try:
41 | output = subprocess.Popen([self.avPath, '-w', '-m', '-a', file_path], stdout=subprocess.PIPE).communicate()[0]
42 |
43 | if not "Infections found : 0(0)" in output:
44 | self.score = 10
45 | result = output.split('\n')[6].split(' ')[1]
46 | else:
47 | result = 'OK'
48 | except (Exception) as e:
49 | raise Exception("Avg-Antivir scan file '%s' Failed" % e)
50 |
51 | return result
52 |
--------------------------------------------------------------------------------
/src/processing/antivirus_avg.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = antivirus_avg
3 | Module = antivirus_avg
4 |
5 | [Documentation]
6 | Description = Avg AntiVirus Scan (http://free.avg.com)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/antivirus_avira.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import re
7 | import subprocess
8 |
9 | from core.abstracts import Processing
10 |
11 |
12 | try:
13 | from yapsy.IPlugin import IPlugin
14 | except ImportError:
15 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
16 |
17 | log = logging.getLogger("ProcessingAviraAv")
18 |
19 | class Avira(IPlugin, Processing):
20 |
21 | def run(self, objfile):
22 | self.key = "AntivirusScanAvira"
23 | self.score = 0
24 | self.avPath = self.options.get("avira_path", None)
25 | self.aviraHeurLevel = self.options.get("avira_heur_level", None)
26 | result = {}
27 |
28 | try:
29 | result["Avira"] = self.avira(objfile.file.temp_file)
30 | except (Exception) as e:
31 | log.error("The module \"Avira\" returned the following error: %s" % e)
32 |
33 | return result
34 |
35 | def avira(self, file_path):
36 | # Dictionary containing all the results of this processing.
37 | results = {}
38 | resultFund = None
39 | resultUrl = None
40 |
41 | if not self.avPath:
42 | raise Exception("AviraAV path is not set in the configuration!")
43 |
44 | if self.aviraHeurLevel and (self.aviraHeurLevel < 0 and self.aviraHeurLevel > 3):
45 | self.aviraHeurLevel = 3
46 |
47 | quarantineDir = self.options.get("quarantine-dir", "/tmp/")
48 |
49 | if os.path.isfile(self.avPath):
50 | try:
51 | output = subprocess.Popen([self.avPath, '--batch', '--scan-mode=all', \
52 | '--heur-macro=yes', '--heur-level=' + str(self.aviraHeurLevel), \
53 | '--quarantine-dir=' + quarantineDir,
54 | file_path], stdout=subprocess.PIPE).communicate()[0]
55 |
56 | rpd = re.compile('\sFUND:\s(.+)', re.IGNORECASE)
57 | rpdFind = re.findall(rpd, output)
58 | rpdSorted = sorted(rpdFind)
59 |
60 | r = ''
61 | for r in rpdSorted:
62 | resultFund = r
63 |
64 | if r == '':
65 | resultFund = 'OK'
66 | else:
67 | # Fund AV-Hit
68 | self.score = 10
69 | rpd = re.compile('\sFUND-URL:\s(.+)', re.IGNORECASE)
70 | rpdFind = re.findall(rpd, output)
71 | rpdSorted = sorted(rpdFind)
72 |
73 | r = ''
74 | for r in rpdSorted:
75 | resultUrl = r
76 |
77 | results["scan"] = resultFund
78 |
79 | if resultUrl:
80 | results["url"] = resultUrl
81 |
82 | except (Exception) as e:
83 | raise Exception("Avira-Antivir scan file '%s' Failed" % e)
84 |
85 | return results
86 |
--------------------------------------------------------------------------------
/src/processing/antivirus_avira.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = antivirus_avira
3 | Module = antivirus_avira
4 |
5 | [Documentation]
6 | Description = Avira AntiVirus Scan (http://www.avira.com/de/avira-free-antivirus)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/antivirus_bitDefender.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import re
7 | import subprocess
8 |
9 | from core.abstracts import Processing
10 |
11 |
12 | try:
13 | from yapsy.IPlugin import IPlugin
14 | except ImportError:
15 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
16 |
17 | log = logging.getLogger("ProcessingBitDefenderAv")
18 |
19 | class BitDefender(IPlugin, Processing):
20 |
21 | def run(self, objfile):
22 | self.key = "AntivirusScanBitDefender"
23 | self.score = 0
24 | self.avPath = self.options.get("bdscan_path", None)
25 | result = {}
26 |
27 | try:
28 | result["BitDefender"] = self.bitDefender(objfile.file.temp_file)
29 | except (Exception) as e:
30 | log.error("The module \"BitDefender\" returned the following error: %s" % e)
31 |
32 | return result
33 |
34 | def bitDefender(self, file_path):
35 | result = None
36 |
37 | if not self.avPath:
38 | raise Exception("BitDefender Antivir path is not set in the configuration!")
39 |
40 | if os.path.isfile(self.avPath):
41 | try:
42 | output = subprocess.Popen([self.avPath, file_path], stdout=subprocess.PIPE).communicate()[0]
43 |
44 | if not "Infected files: 0" in output:
45 | self.score = 10
46 |
47 | rpd = re.compile('\sinfected:\s(.+)', re.IGNORECASE)
48 | rpdFind = re.findall(rpd, output)
49 |
50 | r = ''
51 | for r in rpdFind:
52 | result = r
53 | else:
54 | result = 'OK'
55 | except (Exception) as e:
56 | raise Exception("BitDefender-Antivir scan file '%s' Failed" % e)
57 |
58 | log.info(result)
59 | return result
60 |
--------------------------------------------------------------------------------
/src/processing/antivirus_bitDefender.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = antivirus_bitDefender
3 | Module = antivirus_bitDefender
4 |
5 | [Documentation]
6 | Description = BitDefender AntiVirus Scan (http://www.bitdefender.co.uk/)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/antivirus_clamav.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import subprocess
7 |
8 | from core.abstracts import Processing
9 |
10 |
11 | try:
12 | from yapsy.IPlugin import IPlugin
13 | except ImportError:
14 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
15 |
16 | log = logging.getLogger("ProcessingClamAv")
17 |
18 | class ClamAv(IPlugin, Processing):
19 |
20 | def run(self, objfile):
21 | self.key = "AntivirusScanClamAv"
22 | self.score = 0
23 | self.avPath = self.options.get("clamscan_path", None)
24 | result = {}
25 |
26 | try:
27 | result["ClamAv"] = self.clamav(objfile.file.temp_file)
28 | except (Exception) as e:
29 | log.error("The module \"ClamAv\" returned the following error: %s" % e)
30 |
31 | return result
32 |
33 | def clamav(self, file_path):
34 | result = None
35 |
36 | if not self.avPath:
37 | raise Exception("ClamAv path is not set in the configuration!")
38 |
39 | if os.path.isfile(self.avPath):
40 | try:
41 | output = subprocess.Popen([self.avPath, "--no-summary", file_path], \
42 | stdout=subprocess.PIPE).communicate()[0]
43 | result = output.split('\n')[0].split(':')[1]
44 |
45 | if not "OK" in result:
46 | self.score = 10
47 | except (Exception) as e:
48 | raise Exception("ClamAV scan file %s Failed" % e)
49 | return result
50 |
--------------------------------------------------------------------------------
/src/processing/antivirus_clamav.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = antivirus_clamav
3 | Module = antivirus_clamav
4 |
5 | [Documentation]
6 | Description = ClamAv AntiVirus Scan (http://www.clamav.net/lang/en/)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/antivirus_comodo.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import re
7 | import subprocess
8 |
9 | from core.abstracts import Processing
10 |
11 |
12 | try:
13 | from yapsy.IPlugin import IPlugin
14 | except ImportError:
15 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
16 |
17 | log = logging.getLogger("Processing COMODOAv")
18 |
19 | class Comodo(IPlugin, Processing):
20 |
21 | def run(self, objfile):
22 | self.key = "AntivirusScanCOMODO"
23 | self.score = 0
24 | self.avPath = self.options.get("comodo_path", None)
25 | result = {}
26 |
27 | try:
28 | result["COMODO"] = self.comodo(objfile.file.temp_file)
29 | except (Exception) as e:
30 | log.error("The module \"COMODO\" returned the following error: %s" % e)
31 |
32 | return result
33 |
34 | def comodo(self, file_path):
35 | result = None
36 |
37 | if not self.avPath:
38 | raise Exception("COMODO Antivir path is not set in the configuration!")
39 |
40 | if os.path.isfile(self.avPath):
41 | try:
42 | output = subprocess.Popen([self.avPath, '-vs', file_path], stdout=subprocess.PIPE).communicate()[0]
43 |
44 | if not "Number of Found Viruses: 0" in output:
45 | self.score = 10
46 |
47 | rpd = re.compile('\sFound Virus, Malware Name is\s(.+)', re.IGNORECASE)
48 | rpdFind = re.findall(rpd, output)
49 |
50 | r = ''
51 | for r in rpdFind:
52 | result = r
53 | else:
54 | result = 'OK'
55 | except (Exception) as e:
56 | raise Exception("COMODO Antivir scan file '%s' Failed" % e)
57 |
58 | log.info(result)
59 | return result
60 |
--------------------------------------------------------------------------------
/src/processing/antivirus_comodo.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = antivirus_comodo
3 | Module = antivirus_comodo
4 |
5 | [Documentation]
6 | Description = COMODO Antivirus Scan (http://www.comodo.com/)
7 | Author = Mark Lawrenz
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/antivirus_eset.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import re
7 | import subprocess
8 |
9 | from core.abstracts import Processing
10 |
11 |
12 | try:
13 | from yapsy.IPlugin import IPlugin
14 | except ImportError:
15 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
16 |
17 | log = logging.getLogger("Processing ESET Antivir")
18 |
19 | class Eset(IPlugin, Processing):
20 |
21 | def run(self, objfile):
22 | self.key = "AntivirusScanESET"
23 | self.score = 0
24 | self.avPath = self.options.get("eset_path", None)
25 | result = {}
26 |
27 | try:
28 | result["ESET"] = self.eset(objfile.file.temp_file)
29 | except (Exception) as e:
30 | log.error("The module \"ESET\" returned the following error: %s" % e)
31 |
32 | return result
33 |
34 | def eset(self, file_path):
35 | result = None
36 |
37 | if not self.avPath:
38 | raise Exception("ESET Antivir path is not set in the configuration!")
39 |
40 | if os.path.isfile(self.avPath):
41 | try:
42 | output = subprocess.Popen([self.avPath, '--clean-mode=none', file_path], stdout=subprocess.PIPE).communicate()[0]
43 |
44 | if (("threat=" in output) and (not 'threat=""' in output)):
45 | self.score = 10
46 | rpd = re.compile('\sthreat=\"(.+)\",\saction=', re.IGNORECASE)
47 | rpdFind = re.findall(rpd, output)
48 |
49 | r = ''
50 | for r in rpdFind:
51 | result = r
52 | else:
53 | result = 'OK'
54 |
55 | except (Exception) as e:
56 | raise Exception("ESET Antivir scan file '%s' Failed" % e)
57 |
58 | log.info(result)
59 |
60 | return result
61 |
--------------------------------------------------------------------------------
/src/processing/antivirus_eset.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = antivirus_eset
3 | Module = antivirus_eset
4 |
5 | [Documentation]
6 | Description = ESET File Security für Linux v4.0.10 (http://www.eset.com)
7 | Author = Mark Lawrenz
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/antivirus_fprot.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import re
7 | import subprocess
8 |
9 | from core.abstracts import Processing
10 |
11 |
12 | try:
13 | from yapsy.IPlugin import IPlugin
14 | except ImportError:
15 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
16 |
17 | log = logging.getLogger("ProcessingFProtAv")
18 |
19 | class FProt(IPlugin, Processing):
20 |
21 | def run(self, objfile):
22 | self.key = "AntivirusScanFProt"
23 | self.score = 0
24 | self.avPath = self.options.get("fprot_path", None)
25 | result = {}
26 |
27 | try:
28 | result["FProt"] = self.fprot(objfile.file.temp_file)
29 | except (Exception) as e:
30 | log.error("The module \"F-Prot\" returned the following error: %s" % e)
31 |
32 | return result
33 |
34 | def fprot(self, file_path):
35 | result = None
36 |
37 | if not self.avPath:
38 | raise Exception("F-Prot Antivir path is not set in the configuration!")
39 |
40 | if os.path.isfile(self.avPath):
41 | try:
42 | output = subprocess.Popen([self.avPath, '-r', '-f', '--scanlevel=4', '--heurlevel=4', '--adware', '--applications',
43 | file_path], stdout=subprocess.PIPE).communicate()[0]
44 |
45 | if not "Infected files: 0" in output:
46 | self.score = 10
47 |
48 | rpd = re.compile('\[Found\s.*\]\s<(.+)>\s\s', re.IGNORECASE)
49 | rpdFind = re.findall(rpd, output)
50 |
51 | r = ''
52 | for r in rpdFind:
53 | result = r
54 | else:
55 | result = 'OK'
56 | except (Exception) as e:
57 | raise Exception("F-Prot-Antivir scan file '%s' Failed" % e)
58 |
59 | log.info(result)
60 | return result
61 |
--------------------------------------------------------------------------------
/src/processing/antivirus_fprot.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = antivirus_fprot
3 | Module = antivirus_fprot
4 |
5 | [Documentation]
6 | Description = F-Prot AntiVirus Scan (http://www.f-prot.com/)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/antivirus_fsecure.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import re
7 | import subprocess
8 |
9 | from core.abstracts import Processing
10 |
11 |
12 | try:
13 | from yapsy.IPlugin import IPlugin
14 | except ImportError:
15 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
16 |
17 | log = logging.getLogger("Processing F-Secure AV")
18 |
19 | class FSecure(IPlugin, Processing):
20 |
21 | def run(self, objfile):
22 | self.key = "AntivirusScanF-Secure"
23 | self.score = 0
24 | self.avPath = self.options.get("fsecure_path", None)
25 | result = {}
26 |
27 | try:
28 | result["F-Secure"] = self.fsecure(objfile.file.temp_file)
29 | except (Exception) as e:
30 | log.error("The module \"F-Secure\" returned the following error: %s" % e)
31 |
32 | return result
33 |
34 | def fsecure(self, file_path):
35 | result = None
36 |
37 | if not self.avPath:
38 | raise Exception("F-Secure Antivir path is not set in the configuration!")
39 |
40 | if os.path.isfile(self.avPath):
41 | try:
42 | output = subprocess.Popen([self.avPath, '--virus-action1=none', file_path], stdout=subprocess.PIPE).communicate()[0]
43 |
44 |
45 | if "Infected:" in output:
46 | self.score = 10
47 |
48 | rpd = re.compile('\sInfected:\s(.+)', re.IGNORECASE)
49 | rpdFind = re.findall(rpd, output)
50 |
51 | r = ''
52 | for r in rpdFind:
53 | result = r
54 |
55 | elif "Riskware:" in output:
56 | self.score = 10
57 |
58 | rpd = re.compile('\sRiskware:\s(.+)', re.IGNORECASE)
59 | rpdFind = re.findall(rpd, output)
60 |
61 | r = ''
62 | for r in rpdFind:
63 | result = r
64 | else:
65 | result = 'OK'
66 | except (Exception) as e:
67 | raise Exception("F-Secure Antivir scan file '%s' Failed" % e)
68 |
69 | log.info(result)
70 | return result
71 |
--------------------------------------------------------------------------------
/src/processing/antivirus_fsecure.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = antivirus_fsecure
3 | Module = antivirus_fsecure
4 |
5 | [Documentation]
6 | Description = F-Secure Linux Security v10.10.142 (http://www.f-secure.com)
7 | Author = Mark Lawrenz
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/antivirus_teamcymru.py:
--------------------------------------------------------------------------------
1 | import os
2 | import logging
3 | import datetime
4 | import simplejson
5 |
6 | from core.abstracts import Processing
7 |
8 | try:
9 | from yapsy.IPlugin import IPlugin
10 | except ImportError:
11 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
12 |
13 | log = logging.getLogger("Processing Teamcymru")
14 |
15 | CMD = 'dig +short x.malware.hash.cymru.com TXT'
16 |
17 | class Teamcymru(IPlugin, Processing):
18 |
19 | def run(self, objfile):
20 | self.key = "Teamcymru"
21 | self.score = -1
22 |
23 | try:
24 | value = self.submit(objfile.file.get_fileMd5())
25 | if value:
26 | malwarepercent = value.get("malwarepercent")
27 |
28 | self.score = 10
29 |
30 | if malwarepercent > 10 and malwarepercent < 30:
31 | self.score = 25
32 | elif malwarepercent >= 30:
33 | self.score = 50
34 |
35 | return value
36 | except (Exception) as e:
37 | log.error("The module \"Teamcymru\" returned the following error: %s" % e)
38 |
39 | return
40 |
41 | def submit(self, md5):
42 | cmd = CMD.replace('x', md5)
43 | log.debug('Submit '+ cmd)
44 | result=os.popen(cmd)
45 |
46 | result=result.readlines()
47 |
48 | if len(result)> 0:
49 | result=result[0]
50 | result=result.replace('\n','')
51 | result=result.replace('"','')
52 | if result != '127.0.0.2':
53 | timestamp=int(result.split(' ')[0])
54 | lastseen = datetime.datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
55 | malwarepercent=result.split(' ')[1]
56 | data = {"lastseen":lastseen,
57 | "malwarepercent":malwarepercent} #anti-virus package detection rate
58 | return data
59 |
--------------------------------------------------------------------------------
/src/processing/antivirus_teamcymru.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = antivirus_teamcymru
3 | Module = antivirus_teamcymru
4 |
5 | [Documentation]
6 | Description = Malware Hash Registry (MHR) lookup (https://www.team-cymru.org)
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/net_getOwnLocation.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import re
6 | import socket
7 |
8 | from core.abstracts import Processing
9 | import core.commonutils as commonutils
10 |
11 |
12 | try:
13 | from BeautifulSoup import BeautifulSoup as bs
14 | except ImportError:
15 | raise ImportError, 'Beautiful Soup parser: http://www.crummy.com/software/BeautifulSoup/'
16 |
17 | try:
18 | from yapsy.IPlugin import IPlugin
19 | except ImportError:
20 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
21 |
22 | log = logging.getLogger("ProcessingGetOwnLocations")
23 |
24 | class getOwnLocation(IPlugin, Processing):
25 |
26 | def run(self, objfile):
27 | self.key = "OwnLocation"
28 | self.score = -1
29 |
30 | result = self.wieistmeineip()
31 | return result
32 |
33 | def wieistmeineip(self):
34 | result = {}
35 | # Save original socket
36 | originalSocket = socket.socket
37 | # Set TOR Socks proxy
38 | commonutils.setTorProxy()
39 |
40 | try:
41 | # Load
42 | soup = self.parse("http://www.wieistmeineip.de")
43 | location = soup.findAll("div", { "class" : "location" })[0]
44 | location = bs(location.text, convertEntities=bs.HTML_ENTITIES)
45 |
46 | ip = soup.findAll('div', id='ipv4')[0]
47 | raw_ip = bs(ip.text, convertEntities=bs.HTML_ENTITIES)
48 | pattern = re.compile('[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
49 | ip = re.search(pattern, raw_ip.text)
50 |
51 | result["ipaddress"] = ip.group(0)
52 | result["country"] = str(location)
53 | finally:
54 | # Removing SOCKS Tor Proxy
55 | socket.socket = originalSocket
56 |
57 | return result
58 |
59 |
--------------------------------------------------------------------------------
/src/processing/net_getOwnLocation.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = net_getOwnLocation
3 | Module = net_getOwnLocation
4 |
5 | [Documentation]
6 | Description = Returns the own internet location.
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/net_inetSourceAnalysis.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = net_inetSourceAnalysis
3 | Module = net_inetSourceAnalysis
4 |
5 | [Documentation]
6 | Description = Check IP and Host for reputation.
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/ole_officescan.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = ole_officescan
3 | Module = ole_officescan
4 |
5 | [Documentation]
6 | Description = OLE - Analyze the suspicious Office documents
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/pdf_pdfid.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 |
6 | from core.abstracts import Processing
7 | from utils.pdfid import PDFiD
8 |
9 |
10 | try:
11 | from yapsy.IPlugin import IPlugin
12 | except ImportError:
13 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
14 |
15 | log = logging.getLogger("ProcessingPDFID")
16 |
17 | RISKY_PDF_SECTIONS = ['/OpenAction', '/AA', '/JS', '/JavaScript', '/Launch', '/URI', '/Action', '/GoToR', '/RichMedia', '/ObjStm']
18 |
19 | class PDFID(IPlugin, Processing):
20 |
21 | def run(self, objfile):
22 | """Gets PDF identify and informations.
23 | """
24 | self.key = "PDFID"
25 | self.score = -1
26 | returnValue = None
27 |
28 | try:
29 | pdfIdXML = PDFiD(file=objfile.file.temp_file, allNames=False, extraData=True, disarm=False, force=True)
30 | returnValue = self.xml2dic(pdfIdXML)
31 | log.debug("PDFID returns: %s" % returnValue)
32 | except Exception, e:
33 | log.warn("Error - PDFID returns: %s" % e)
34 |
35 | return returnValue
36 |
37 | def xml2dic(self, xmlDoc):
38 | scoreHit = 0
39 | # Get Top Layer Data
40 | errorOccured = xmlDoc.documentElement.getAttribute('ErrorOccured')
41 | errorMessage = xmlDoc.documentElement.getAttribute('ErrorMessage')
42 | header = xmlDoc.documentElement.getAttribute('Header')
43 | isPdf = xmlDoc.documentElement.getAttribute('IsPDF')
44 |
45 | # extra data
46 | countEof = xmlDoc.documentElement.getAttribute('CountEOF')
47 | countChatAfterLastEof = xmlDoc.documentElement.getAttribute('CountCharsAfterLastEOF')
48 | totalEntropy = xmlDoc.documentElement.getAttribute('TotalEntropy')
49 | streamEntropy = xmlDoc.documentElement.getAttribute('StreamEntropy')
50 | nonStreamEntropy = xmlDoc.documentElement.getAttribute('NonStreamEntropy')
51 |
52 | keywords = []
53 |
54 | # grab all keywords
55 | for node in xmlDoc.documentElement.getElementsByTagName('Keywords')[0].childNodes:
56 | name = node.getAttribute('Name')
57 | count = int(node.getAttribute('Count'))
58 | if int(node.getAttribute('HexcodeCount')) > 0:
59 | hexCount = int(node.getAttribute('HexcodeCount'))
60 | else:
61 | hexCount = 0
62 |
63 | if name in RISKY_PDF_SECTIONS and count > 0:
64 | name = "[RISKY] %s" % name
65 | scoreHit += 1
66 |
67 | if name == "/Page" and count < 2:
68 | scoreHit += 1
69 |
70 | keyword = { 'count':count, 'hexcodecount':hexCount, 'name':name }
71 | keywords.append(keyword)
72 |
73 | if totalEntropy > 5.9:
74 | scoreHit += 1
75 |
76 | data = {'header':header,
77 | 'isPdf':isPdf,
78 | 'errorOccured':errorOccured,
79 | 'errorMessage':errorMessage,
80 | 'totalEntropy':totalEntropy,
81 | 'streamEntropy':streamEntropy,
82 | 'countEof':countEof,
83 | 'countChatAfterLastEof':countChatAfterLastEof,
84 | 'nonStreamEntropy':nonStreamEntropy,
85 | 'keywords':keywords }
86 |
87 | # Calculate Scoring
88 | if scoreHit == 2:
89 | self.score = 8
90 | elif scoreHit > 2:
91 | self.score = 10
92 |
93 | return data
94 |
--------------------------------------------------------------------------------
/src/processing/pdf_pdfid.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = pdf_pdfid
3 | Module = pdf_pdfid
4 |
5 | [Documentation]
6 | Description = PDF - Analyze the suspicious PDF documents
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/pe_pefile.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = pe_peid
3 | Module = pe_peid
4 |
5 | [Documentation]
6 | Description = PE - Detects most common packers, cryptors and compilers for PE files
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/pe_peid.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 |
7 | from core.abstracts import Processing
8 | from core.constants import RAGPICKER_ROOT
9 | from utils.pefile import PE
10 | from utils.pefile import PEFormatError
11 | from utils.peutils import SignatureDatabase
12 |
13 |
14 | try:
15 | from yapsy.IPlugin import IPlugin
16 | except ImportError:
17 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
18 |
19 | log = logging.getLogger("ProcessingPEID")
20 |
21 | class PEID(IPlugin, Processing):
22 |
23 | def run(self, objfile):
24 | """Gets PEID signatures.
25 | @return: matched signatures or None.
26 | """
27 | self.key = "PEID"
28 | self.score = -1
29 |
30 | try:
31 | pe = PE(data=objfile.file.file_data)
32 | signatures = SignatureDatabase(os.path.join(RAGPICKER_ROOT, 'data', 'peiddb.txt'))
33 | match = signatures.match(pe, ep_only=True)
34 | if match:
35 | log.info("PEID match: %s" % match)
36 | self.score = 10
37 | return match
38 | except PEFormatError, e:
39 | log.warn("Error - No Portable Executable: %s" % e)
40 |
41 | return None
42 |
--------------------------------------------------------------------------------
/src/processing/pe_peid.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = pe_pefile
3 | Module = pe_pefile
4 |
5 | [Documentation]
6 | Description = PE - pefile is a module to read and work with PE (Portable Executable) files
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/pe_verifySigs.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = pe_verifySigs
3 | Module = pe_verifySigs
4 |
5 | [Documentation]
6 | Description = PE - Compute hashes, validate digital signature and list details
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/processing/rtf_rtfscan.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = rtf_rtfscan
3 | Module = rtf_rtfscan
4 |
5 | [Documentation]
6 | Description = RTF - Analyze the suspicious RTF documents
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/reporting/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/reporting/__init__.py
--------------------------------------------------------------------------------
/src/reporting/codeDB.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = codeDB
3 | Module = codeDB
4 |
5 | [Documentation]
6 | Description = codeDB report-plugin for Viviane's Code Database
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/reporting/filedump.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 | import os
6 | import tempfile
7 |
8 | from core.abstracts import Report
9 |
10 |
11 | try:
12 | from yapsy.IPlugin import IPlugin
13 | except ImportError:
14 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
15 |
16 | log = logging.getLogger(__name__)
17 |
18 | class FileDump(IPlugin, Report):
19 | """Save downloaded file on the file system"""
20 |
21 | def run(self, results, objfile):
22 | dumpdir = self.options.get("dumpdir", None)
23 | suffix = self.options.get("suffix", None)
24 |
25 | if not dumpdir:
26 | raise Exception("dumpdir not configured, skip")
27 |
28 | try:
29 | if not os.path.exists(dumpdir):
30 | os.makedirs(dumpdir)
31 | d = tempfile.mkdtemp(dir=dumpdir)
32 | except Exception as e:
33 | raise Exception('Could not open %s for writing (%s)', dumpdir, e)
34 | else:
35 | os.rmdir(d)
36 |
37 | dest = dumpdir + objfile.file.get_type()
38 |
39 | if not os.path.exists(dest):
40 | os.makedirs(dest)
41 |
42 | # Save file
43 | fpath = dest + '/' + objfile.file.get_fileMd5() + self.getFileExtension(suffix, objfile.file)
44 | self.saveFile(objfile.file.file_data, fpath)
45 |
46 | # Save unpacked file
47 | if objfile.unpacked_file:
48 | fpath = "%s/%s_unpacked_(%s)%s" % (dest, objfile.unpacked_file.get_fileMd5(), objfile.file.get_fileMd5(), \
49 | self.getFileExtension(suffix, objfile.unpacked_file))
50 | self.saveFile(objfile.unpacked_file.file_data, fpath)
51 |
52 | # Save included files
53 | if len(objfile.included_files) > 0:
54 | log.info("Save included files")
55 | for incl_file in objfile.included_files:
56 | log.info("File: " + incl_file.get_fileMd5())
57 | fpath = "%s/%s_included_(%s)%s" % (dest, incl_file.get_fileMd5(), objfile.file.get_fileMd5(), \
58 | self.getFileExtension(suffix, incl_file))
59 | self.saveFile(incl_file.file_data, fpath)
60 |
61 | return None
62 |
63 | def getFileExtension(self, suffix, file):
64 | if file.file_extension():
65 | file_extension = '.' + file.file_extension() + suffix
66 | else:
67 | file_extension = suffix
68 | return file_extension
69 |
70 | def saveFile(self, file_data, fpath):
71 | if not os.path.exists(fpath):
72 | file = open(fpath, 'wb')
73 | file.write(file_data)
74 | file.close
75 | log.info("Saved file %s" % fpath)
76 |
--------------------------------------------------------------------------------
/src/reporting/filedump.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = filedump
3 | Module = filedump
4 |
5 | [Documentation]
6 | Description = Save sample file on the file system
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/reporting/hpfriends.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import datetime
5 | import json
6 | import jsonpickle
7 | import logging
8 |
9 | from core.abstracts import Report
10 | from core.commonutils import DatetimeHandler
11 |
12 |
13 | try:
14 | from yapsy.IPlugin import IPlugin
15 | except ImportError:
16 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
17 |
18 | try:
19 | import utils.hpfeeds as hpfeeds
20 | except ImportError:
21 | raise ImportError, 'Unable to import HPFeeds library: https://github.com/rep/hpfeeds'
22 |
23 | log = logging.getLogger("ReportingHPFriends")
24 |
25 | class HPFriends(IPlugin, Report):
26 |
27 | def run(self, results, objfile):
28 | host = self.options.get("host", "hpfriends.honeycloud.net")
29 | port = self.options.get("port", 20000)
30 | ident = self.options.get("ident")
31 | secret = self.options.get("secret")
32 | channel_reports = self.options.get("channel_reports")
33 | channel_files = self.options.get("channel_files")
34 |
35 | if not ident or not secret:
36 | raise Exception("HPFriends Identifier and Secret not configurated")
37 |
38 | try:
39 | # Connect to HPFriends
40 | hpc = hpfeeds.HPC(host, port, ident, secret, timeout=60)
41 |
42 | if channel_reports:
43 | # publish JSON-Report on the HPFriends channel
44 | log.info("publish JSON-Report on the HPFriends channel %s" % channel_reports)
45 |
46 | jsonpickle.set_encoder_options('simplejson', indent=4)
47 | jsonpickle.handlers.registry.register(datetime.datetime, DatetimeHandler)
48 | hpc.publish(channel_reports, jsonpickle.encode(results))
49 |
50 | if channel_files:
51 | # publish RAW-File as BASE64 on the HPFriends channel
52 | log.info("publish BASE64 on the HPFriends channel %s" % channel_files)
53 | hpc.publish(channel_files, json.dumps(objfile.file.get_fileB64encode(), sort_keys=False, indent=4))
54 | except hpfeeds.FeedException as e:
55 | raise Exception("publish on the channel failed: %s" % e)
56 | finally:
57 | hpc.close()
58 |
--------------------------------------------------------------------------------
/src/reporting/hpfriends.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = hpfriends
3 | Module = hpfriends
4 |
5 | [Documentation]
6 | Description = Publishes the results on an HPFeeds channel
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/reporting/jsondump.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import codecs
5 | import datetime
6 | import jsonpickle
7 | import logging
8 | import os
9 | import tempfile
10 | import uuid
11 |
12 | from core.abstracts import Report
13 | from core.commonutils import DatetimeHandler
14 | from core.commonutils import UUIDHandler
15 | from core.commonutils import convertDirtyDict2ASCII
16 |
17 |
18 | try:
19 | from yapsy.IPlugin import IPlugin
20 | except ImportError:
21 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program : http://yapsy.sourceforge.net'
22 |
23 | log = logging.getLogger(__name__)
24 |
25 | class JsonDump(IPlugin, Report):
26 | """Saves analysis results in JSON format."""
27 |
28 | def run(self, results, objfile):
29 | """Writes report.
30 | @param results: results dict.
31 | @param objfile: file object
32 | @raise Exception: if fails to write report.
33 | """
34 | dumpdir = self.options.get("dumpdir", None)
35 |
36 | if not dumpdir:
37 | raise Exception("dumpdir not configured, skip")
38 |
39 | try:
40 | if not os.path.exists(dumpdir):
41 | os.makedirs(dumpdir)
42 | d = tempfile.mkdtemp(dir=dumpdir)
43 | except Exception as e:
44 | raise Exception('Could not open %s for writing (%s)', dumpdir, e)
45 | else:
46 | os.rmdir(d)
47 |
48 | url_md5 = results["Info"]["url"]["md5"]
49 | file_md5 = results["Info"]["file"]["md5"]
50 | jfile = url_md5 + "_" + file_md5 + ".json"
51 |
52 | try:
53 | jsonpickle.set_encoder_options('simplejson', indent=4)
54 | jsonpickle.handlers.registry.register(datetime.datetime, DatetimeHandler)
55 | jsonpickle.handlers.registry.register(uuid.UUID, UUIDHandler)
56 | jsonReport = jsonpickle.encode(results)
57 | except (UnicodeError, TypeError):
58 | jsonReport = jsonpickle.encode(convertDirtyDict2ASCII(results))
59 |
60 | try:
61 | if not os.path.exists(dumpdir + jfile):
62 | report = codecs.open(os.path.join(dumpdir, jfile), "w", "utf-8")
63 | report.write(jsonReport)
64 | report.close()
65 | except (TypeError, IOError) as e:
66 | raise Exception("Failed to generate JSON report: %s" % e)
67 |
--------------------------------------------------------------------------------
/src/reporting/jsondump.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = jsondump
3 | Module = jsondump
4 |
5 | [Documentation]
6 | Description = Saves analysis results in JSON format
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/reporting/mongodb.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import logging
5 |
6 | from yapsy.IPlugin import IPlugin
7 | from core.database import Database
8 | from core.abstracts import Report
9 |
10 | log = logging.getLogger("MongoDB")
11 |
12 | class MongoDB(IPlugin, Report):
13 | """Stores report in MongoDB."""
14 |
15 | def run(self, results, objfile):
16 | """Writes report.
17 | @param results: analysis results dictionary.
18 | @param objfile: file object
19 | """
20 | database = Database()
21 |
22 | # Count query using URL hash and file hash
23 | count = database.countRagpickerDB(results["Info"]["file"]["md5"], results["Info"]["url"]["md5"])
24 |
25 | # If report available for the file and url -> not insert
26 | if count == 0:
27 | # Create a copy of the dictionary. This is done in order to not modify
28 | # the original dictionary and possibly compromise the following
29 | # reporting modules.
30 | report = dict(results)
31 | # Store the report
32 | database.insertRagpickerDB(report)
33 |
34 | count = database.countFamilyDB(objfile.family.parentObjectSHA256)
35 | if count == 0:
36 | if objfile.family.unpackedObjectSHA256 != "" or len(objfile.family.siblingObjectsSHA256) > 0:
37 | log.info(objfile.family)
38 | report = dict(objfile.family.__dict__)
39 | database.insertFamily(report)
40 |
41 | def deleteAll(self):
42 | """Deletes all reports.
43 | """
44 | # Alle Ragpicker-Daten aus der MongoDB loeschen
45 | count = Database().deleteRagpickerDB()
46 |
47 | print "*** MongoDB (Ragpicker)***"
48 | print "deleted documents:" + str(count)
49 | print ""
50 |
51 | count = Database().deleteFamilyDB()
52 |
53 | print "*** MongoDB (Family)***"
54 | print "deleted documents:" + str(count)
55 | print ""
56 |
57 | count = Database().deleteSandboxTaskQueueDB()
58 |
59 | print "*** MongoDB (SandboxTaskQueue)***"
60 | print "deleted documents:" + str(count)
61 | print ""
62 |
--------------------------------------------------------------------------------
/src/reporting/mongodb.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = mongodb
3 | Module = mongodb
4 |
5 | [Documentation]
6 | Description = Reporting-Modul for MongoDB
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/reporting/mysql.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | from yapsy.IPlugin import IPlugin
5 |
6 | from core.abstracts import Report
7 |
8 | class MySQL(IPlugin, Report):
9 | """Stores data from long-run analysis in MySQL."""
10 |
11 | def run(self, results, objfile):
12 | # Import muss hier stehen, sonst kommt es bei Konfiguration ohne Mysql zum Fehler
13 | from core.databaseMysql import DatabaseMySQL
14 | """Writes report.
15 | @param results: analysis results dictionary.
16 | @param objfile: file object
17 | """
18 | database = DatabaseMySQL()
19 |
20 | print "mysql.py Methode Run"
21 | """
22 | # Count query using URL hash and file hash
23 | count = database.countRagpickerDB(results["Info"]["file"]["md5"], results["Info"]["url"]["md5"])
24 |
25 | # If report available for the file and url -> not insert
26 | if count == 0:
27 | # Create a copy of the dictionary. This is done in order to not modify
28 | # the original dictionary and possibly compromise the following
29 | # reporting modules.
30 | report = dict(results)
31 | # Store the report
32 | database.insertRagpickerDB(report)
33 | """
34 | def deleteAll(self):
35 | """Deletes all reports.
36 | """
37 | print "mysql.py Methode DeleteAll"
38 | """
39 | # Alle Ragpicker-Daten aus der MongoDB loeschen
40 | count = Database().deleteRagpickerDB()
41 |
42 | print "*** MongoDB (Ragpicker)***"
43 | print "deleted documents:" + str(count)
44 | print ""
45 | """
--------------------------------------------------------------------------------
/src/reporting/mysql.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = mysql
3 | Module = mysql
4 |
5 | [Documentation]
6 | Description = Reporting-Modul for MySQL
7 | Author = Mark Lawrenz
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/reporting/reporthtml.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 |
4 | import codecs
5 | import logging
6 | import os
7 | import tempfile
8 |
9 | from core.abstracts import Report
10 | from core.commonutils import convertDirtyDict2ASCII
11 | from core.constants import RAGPICKER_ROOT
12 |
13 |
14 | try:
15 | from yapsy.IPlugin import IPlugin
16 | except ImportError:
17 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program: http://yapsy.sourceforge.net'
18 |
19 | try:
20 | from jinja2.loaders import FileSystemLoader
21 | from jinja2.environment import Environment
22 | except ImportError:
23 | raise ImportError("Jinja2 Python library is required to generate HTML reports: http://jinja.pocoo.org")
24 |
25 | log = logging.getLogger(__name__)
26 |
27 | class ReportHTML(IPlugin, Report):
28 | """Save report in HTML format."""
29 |
30 | def run(self, results, objfile):
31 | dumpdir = self.options.get("dumpdir", None)
32 |
33 | if not dumpdir:
34 | raise Exception("dumpdir not configured, skip")
35 |
36 | try:
37 | if not os.path.exists(dumpdir):
38 | os.makedirs(dumpdir)
39 | d = tempfile.mkdtemp(dir=dumpdir)
40 | except Exception as e:
41 | raise Exception('Could not open %s for writing (%s)', dumpdir, e)
42 | else:
43 | os.rmdir(d)
44 |
45 | url_md5 = results["Info"]["url"]["md5"]
46 | file_md5 = results["Info"]["file"]["md5"]
47 | jfile = url_md5 + "_" + file_md5 + ".html"
48 |
49 | if not os.path.exists(dumpdir + jfile):
50 | try:
51 | env = Environment(autoescape=True)
52 | env.loader = FileSystemLoader(os.path.join(RAGPICKER_ROOT, "data", "html"))
53 | template = env.get_template("report.html")
54 | reporthtml = template.render({"results" : results})
55 | except UnicodeDecodeError:
56 | reporthtml = template.render({"results" : convertDirtyDict2ASCII(results)})
57 | except Exception as e:
58 | raise Exception("Failed to generate HTML report: %s" % e)
59 |
60 | try:
61 | reportfile = codecs.open(os.path.join(dumpdir, jfile), "w", "utf-8")
62 | reportfile.write(reporthtml)
63 | reportfile.close()
64 | except (TypeError, IOError) as e:
65 | raise Exception("Failed to write HTML report: %s" % e)
66 |
--------------------------------------------------------------------------------
/src/reporting/reporthtml.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = reporthtml
3 | Module = reporthtml
4 |
5 | [Documentation]
6 | Description = HTML Reporting-Modul
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/reporting/reportxml.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2015 Ragpicker Developers.
2 | # This file is part of Ragpicker Malware Crawler - http://code.google.com/p/malware-crawler/
3 | # coding: utf-8
4 |
5 | import codecs
6 | import logging
7 | import os
8 | import tempfile
9 |
10 | from core.abstracts import Report
11 | from core.commonutils import convertDirtyDict2ASCII
12 | import utils.dict2xml as dict2xml
13 |
14 |
15 | try:
16 | from yapsy.IPlugin import IPlugin
17 | except ImportError:
18 | raise ImportError, 'Yapsy (Yet Another Plugin System) is required to run this program: http://yapsy.sourceforge.net'
19 |
20 | log = logging.getLogger(__name__)
21 |
22 | class ReportXML(IPlugin, Report):
23 | """Save report in XML format."""
24 |
25 | def run(self, results, objfile):
26 | dumpdir = self.options.get("dumpdir", None)
27 |
28 | if not dumpdir:
29 | raise Exception("dumpdir not configured, skip")
30 |
31 | try:
32 | if not os.path.exists(dumpdir):
33 | os.makedirs(dumpdir)
34 | d = tempfile.mkdtemp(dir=dumpdir)
35 | except Exception as e:
36 | raise Exception('Could not open %s for writing (%s)', dumpdir, e)
37 | else:
38 | os.rmdir(d)
39 |
40 | url_md5 = results["Info"]["url"]["md5"]
41 | file_md5 = results["Info"]["file"]["md5"]
42 | jfile = url_md5 + "_" + file_md5 + ".xml"
43 |
44 | if not os.path.exists(dumpdir + jfile):
45 | try:
46 | reportxml = dict2xml.dicttoxml(results)
47 | except UnicodeDecodeError:
48 | reportxml = dict2xml.dicttoxml(convertDirtyDict2ASCII(results))
49 | except Exception as e:
50 | raise Exception("Failed to generate XML report: %s" % e)
51 |
52 | try:
53 |
54 | reportfile = codecs.open(os.path.join(dumpdir, jfile), "w", "utf-8")
55 | reportfile.write(reportxml)
56 | reportfile.close()
57 | except (TypeError, IOError) as e:
58 | raise Exception("Failed to write XML report: %s" % e)
59 |
60 |
--------------------------------------------------------------------------------
/src/reporting/reportxml.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = reportxml
3 | Module = reportxml
4 |
5 | [Documentation]
6 | Description = Store analysis results as xml document
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/reporting/vxcage.yapsy-plugin:
--------------------------------------------------------------------------------
1 | [Core]
2 | Name = vxcage
3 | Module = vxcage
4 |
5 | [Documentation]
6 | Description = VxCage is a Python application for managing a malware samples repository
7 | Author = Robby Zeitfuchs
8 | Version = 1.0
--------------------------------------------------------------------------------
/src/statistics.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # _ _
3 | # _ __ __ _ __ _ _ __ (_) ___ | | __ ___ _ __
4 | # | '__| / _` | / _` || '_ \ | | / __|| |/ / / _ \| '__|
5 | # | | | (_| || (_| || |_) || || (__ | < | __/| |
6 | # |_| \__,_| \__, || .__/ |_| \___||_|\_\ \___||_|
7 | # |___/ |_|
8 | #
9 | # Plugin based malware crawler.
10 | # Use this tool if you are testing antivirus products, collecting malware
11 | # for another analyzer/zoo.
12 | # Many thanks to the cuckoo-sandbox team for the Architectural design ideas.
13 | # Includes code from cuckoo-sandbox (c) 2013 http://www.cuckoosandbox.org
14 | # and mwcrawler, (c) 2012 Ricardo Dias
15 | #
16 | # http://code.google.com/p/malware-crawler/
17 | #
18 | # Robby Zeitfuchs - robby@zeitfuchs.org - 2013-2015
19 | # Mark Lawrenz - Mark.Lawrenz@web.de
20 | #
21 | # any subjection, tips, improvement are welcome
22 | #
23 | # Licence: GNU GPL v.3.0
24 | #
25 | # This program is free software; you can redistribute it and/or modify
26 | # it under the terms of the GNU General Public License as published by
27 | # the Free Software Foundation; either version 3 of the License, or
28 | # (at your option) any later version.
29 | #
30 | # This program is distributed in the hope that it will be useful,
31 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
32 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 | # GNU General Public License for more details.
34 |
35 | import argparse
36 | import logging
37 |
38 | from utils.logo import logo
39 | from core.statistics import Statistics
40 |
41 | log = logging.getLogger("Main")
42 |
43 | if __name__ == '__main__':
44 |
45 | parser = argparse.ArgumentParser(description='Ragpicker Statistics')
46 | subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands', help='additional help')
47 |
48 | parser_long = subparsers.add_parser('long', help="Show statistics (long version)")
49 | parser_long.set_defaults(which='long')
50 | parser_short = subparsers.add_parser('short', help="Show statistics (short version)")
51 | parser_short.set_defaults(which='short')
52 | parser_av = subparsers.add_parser('av', help="Show statistics (AV version)")
53 | parser_av.set_defaults(which='av')
54 |
55 | args = vars(parser.parse_args())
56 |
57 | logo()
58 |
59 | if args['which'] == 'long':
60 | Statistics().runStatisticsLong()
61 | elif args['which'] == 'short':
62 | Statistics().runStatisticsShort()
63 | elif args['which'] == 'av':
64 | Statistics().runStatisticsAV()
--------------------------------------------------------------------------------
/src/utils/OfficeMalScanner/Cadt.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/OfficeMalScanner/Cadt.dll
--------------------------------------------------------------------------------
/src/utils/OfficeMalScanner/DisView.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/OfficeMalScanner/DisView.exe
--------------------------------------------------------------------------------
/src/utils/OfficeMalScanner/LZNT1Decompress.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/OfficeMalScanner/LZNT1Decompress.dll
--------------------------------------------------------------------------------
/src/utils/OfficeMalScanner/MalHost-Setup.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/OfficeMalScanner/MalHost-Setup.exe
--------------------------------------------------------------------------------
/src/utils/OfficeMalScanner/OfficeMalScanner.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/OfficeMalScanner/OfficeMalScanner.exe
--------------------------------------------------------------------------------
/src/utils/OfficeMalScanner/RTFScan.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/OfficeMalScanner/RTFScan.exe
--------------------------------------------------------------------------------
/src/utils/OfficeMalScanner/Unzipper.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/OfficeMalScanner/Unzipper.dll
--------------------------------------------------------------------------------
/src/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/__init__.py
--------------------------------------------------------------------------------
/src/utils/oletools/LICENSE.txt:
--------------------------------------------------------------------------------
1 | LICENSE for the python-oletools package:
2 |
3 | This license applies to the python-oletools package, apart from the thirdparty
4 | folder which contains third-party files published with their own license.
5 |
6 | The python-oletools package is copyright (c) 2012-2015 Philippe Lagadec (http://www.decalage.info)
7 |
8 | All rights reserved.
9 |
10 | Redistribution and use in source and binary forms, with or without modification,
11 | are permitted provided that the following conditions are met:
12 |
13 | * Redistributions of source code must retain the above copyright notice, this
14 | list of conditions and the following disclaimer.
15 | * Redistributions in binary form must reproduce the above copyright notice,
16 | this list of conditions and the following disclaimer in the documentation
17 | and/or other materials provided with the distribution.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 |
31 | ----------
32 |
33 | olevba contains modified source code from the officeparser project, published
34 | under the following MIT License (MIT):
35 |
36 | officeparser is copyright (c) 2014 John William Davison
37 |
38 | Permission is hereby granted, free of charge, to any person obtaining a copy
39 | of this software and associated documentation files (the "Software"), to deal
40 | in the Software without restriction, including without limitation the rights
41 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
42 | copies of the Software, and to permit persons to whom the Software is
43 | furnished to do so, subject to the following conditions:
44 |
45 | The above copyright notice and this permission notice shall be included in all
46 | copies or substantial portions of the Software.
47 |
48 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
49 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
50 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
51 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
52 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
53 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
54 | SOFTWARE.
55 |
--------------------------------------------------------------------------------
/src/utils/oletools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/oletools/__init__.py
--------------------------------------------------------------------------------
/src/utils/oletools/olemeta.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """
3 | olemeta.py
4 |
5 | olemeta is a script to parse OLE files such as MS Office documents (e.g. Word,
6 | Excel), to extract all standard properties present in the OLE file.
7 |
8 | Usage: olemeta.py
9 |
10 | olemeta project website: http://www.decalage.info/python/olemeta
11 |
12 | olemeta is part of the python-oletools package:
13 | http://www.decalage.info/python/oletools
14 | """
15 |
16 | #=== LICENSE =================================================================
17 |
18 | # olemeta is copyright (c) 2013-2014, Philippe Lagadec (http://www.decalage.info)
19 | # All rights reserved.
20 | #
21 | # Redistribution and use in source and binary forms, with or without modification,
22 | # are permitted provided that the following conditions are met:
23 | #
24 | # * Redistributions of source code must retain the above copyright notice, this
25 | # list of conditions and the following disclaimer.
26 | # * Redistributions in binary form must reproduce the above copyright notice,
27 | # this list of conditions and the following disclaimer in the documentation
28 | # and/or other materials provided with the distribution.
29 | #
30 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
31 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
34 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
36 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 |
41 | #------------------------------------------------------------------------------
42 | # CHANGELOG:
43 | # 2013-07-24 v0.01 PL: - first version
44 | # 2014-11-29 v0.02 PL: - use olefile instead of OleFileIO_PL
45 | # - improved usage display
46 |
47 | __version__ = '0.02'
48 |
49 | #------------------------------------------------------------------------------
50 | # TODO:
51 | # + optparse
52 | # + nicer output: table with fixed columns, datetime, etc
53 | # + CSV output
54 | # + option to only show available properties (by default)
55 |
56 | #=== IMPORTS =================================================================
57 |
58 | import sys
59 | import thirdparty.olefile as olefile
60 |
61 |
62 | #=== MAIN =================================================================
63 |
64 | try:
65 | ole = olefile.OleFileIO(sys.argv[1])
66 | except IndexError:
67 | sys.exit(__doc__)
68 |
69 | # parse and display metadata:
70 | meta = ole.get_metadata()
71 | meta.dump()
72 |
73 | ole.close()
74 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/OleFileIO_PL/LICENSE.txt:
--------------------------------------------------------------------------------
1 | LICENSE for the OleFileIO_PL module:
2 |
3 |
4 | OleFileIO_PL is an improved version of the OleFileIO module from the
5 | Python Imaging Library (PIL).
6 |
7 | OleFileIO_PL changes are Copyright (c) 2005-2013 by Philippe Lagadec
8 |
9 | The Python Imaging Library (PIL) is
10 | Copyright (c) 1997-2005 by Secret Labs AB
11 | Copyright (c) 1995-2005 by Fredrik Lundh
12 |
13 | By obtaining, using, and/or copying this software and/or its associated
14 | documentation, you agree that you have read, understood, and will comply with
15 | the following terms and conditions:
16 |
17 | Permission to use, copy, modify, and distribute this software and its
18 | associated documentation for any purpose and without fee is hereby granted,
19 | provided that the above copyright notice appears in all copies, and that both
20 | that copyright notice and this permission notice appear in supporting
21 | documentation, and that the name of Secret Labs AB or the author(s) not be used
22 | in advertising or publicity pertaining to distribution of the software
23 | without specific, written prior permission.
24 |
25 | SECRET LABS AB AND THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
26 | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
27 | IN NO EVENT SHALL SECRET LABS AB OR THE AUTHORS BE LIABLE FOR ANY SPECIAL,
28 | INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
29 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
30 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
31 | PERFORMANCE OF THIS SOFTWARE.
32 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/OleFileIO_PL/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/oletools/thirdparty/OleFileIO_PL/__init__.py
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/oletools/thirdparty/__init__.py
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/easygui/LICENSE.txt:
--------------------------------------------------------------------------------
1 | LICENSE INFORMATION
2 |
3 | EasyGui version 0.96
4 |
5 | Copyright (c) 2010, Stephen Raymond Ferg
6 |
7 | All rights reserved.
8 |
9 | Redistribution and use in source and binary forms, with or without modification,
10 | are permitted provided that the following conditions are met:
11 |
12 | 1. Redistributions of source code must retain the above copyright notice,
13 | this list of conditions and the following disclaimer.
14 |
15 | 2. Redistributions in binary form must reproduce the above copyright notice,
16 | this list of conditions and the following disclaimer in the documentation and/or
17 | other materials provided with the distribution.
18 |
19 | 3. The name of the author may not be used to endorse or promote products derived
20 | from this software without specific prior written permission.
21 |
22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS"
23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/easygui/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/oletools/thirdparty/easygui/__init__.py
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/CONTRIBUTORS.txt:
--------------------------------------------------------------------------------
1 | CONTRIBUTORS for the olefile project
2 | ====================================
3 |
4 | This is a non-exhaustive list of all the people who helped me improve the
5 | olefile project (formerly OleFileIO_PL), in approximative chronological order.
6 | Please contact me if I forgot to mention your name.
7 |
8 | A big thank you to all of them:
9 |
10 | - Niko Ehrenfeuchter: added support for Jython
11 | - Niko Ehrenfeuchter, Martijn Berger and Dave Jones: helped fix 4K sector support
12 | - Martin Panter: conversion to Python 3.x/2.6+
13 | - mete0r_kr: added support for file-like objects
14 | - chuckleberryfinn: fixed bug in getproperties
15 | - Martijn, Ben G.: bug report for 64 bits platforms
16 | - Philippe Lagadec: main author and maintainer since 2005
17 | - and of course Fredrik Lundh: original author of OleFileIO from 1995 to 2005
18 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/LICENSE.txt:
--------------------------------------------------------------------------------
1 | LICENSE for the olefile package:
2 |
3 | olefile (formerly OleFileIO_PL) is copyright (c) 2005-2014 Philippe Lagadec
4 | (http://www.decalage.info)
5 |
6 | All rights reserved.
7 |
8 | Redistribution and use in source and binary forms, with or without modification,
9 | are permitted provided that the following conditions are met:
10 |
11 | * Redistributions of source code must retain the above copyright notice, this
12 | list of conditions and the following disclaimer.
13 | * Redistributions in binary form must reproduce the above copyright notice,
14 | this list of conditions and the following disclaimer in the documentation
15 | and/or other materials provided with the distribution.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
28 |
29 | ----------
30 |
31 | olefile is based on source code from the OleFileIO module of the Python
32 | Imaging Library (PIL) published by Fredrik Lundh under the following license:
33 |
34 | The Python Imaging Library (PIL) is
35 | - Copyright (c) 1997-2005 by Secret Labs AB
36 | - Copyright (c) 1995-2005 by Fredrik Lundh
37 |
38 | By obtaining, using, and/or copying this software and/or its associated
39 | documentation, you agree that you have read, understood, and will comply with
40 | the following terms and conditions:
41 |
42 | Permission to use, copy, modify, and distribute this software and its
43 | associated documentation for any purpose and without fee is hereby granted,
44 | provided that the above copyright notice appears in all copies, and that both
45 | that copyright notice and this permission notice appear in supporting
46 | documentation, and that the name of Secret Labs AB or the author not be used
47 | in advertising or publicity pertaining to distribution of the software without
48 | specific, written prior permission.
49 |
50 | SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
51 | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
52 | NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL,
53 | INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
54 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
55 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
56 | PERFORMANCE OF THIS SOFTWARE.
57 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/local/bin/python
2 | # -*- coding: latin-1 -*-
3 | """
4 | olefile (formerly OleFileIO_PL)
5 |
6 | Module to read/write Microsoft OLE2 files (also called Structured Storage or
7 | Microsoft Compound Document File Format), such as Microsoft Office 97-2003
8 | documents, Image Composer and FlashPix files, Outlook messages, ...
9 | This version is compatible with Python 2.6+ and 3.x
10 |
11 | Project website: http://www.decalage.info/olefile
12 |
13 | olefile is copyright (c) 2005-2014 Philippe Lagadec (http://www.decalage.info)
14 |
15 | olefile is based on the OleFileIO module from the PIL library v1.1.6
16 | See: http://www.pythonware.com/products/pil/index.htm
17 |
18 | The Python Imaging Library (PIL) is
19 | Copyright (c) 1997-2005 by Secret Labs AB
20 | Copyright (c) 1995-2005 by Fredrik Lundh
21 |
22 | See source code and LICENSE.txt for information on usage and redistribution.
23 | """
24 |
25 | try:
26 | # first try to import olefile for Python 2.6+/3.x
27 | from .olefile import *
28 | # import metadata not covered by *:
29 | from .olefile import __version__, __author__, __date__
30 |
31 | except:
32 | # if it fails, fallback to the old version olefile2 for Python 2.x:
33 | from .olefile2 import *
34 | # import metadata not covered by *:
35 | from .olefile2 import __doc__, __version__, __author__, __date__
36 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/doc/Contribute.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | How to Suggest Improvements, Report Issues or Contribute
11 | This is a personal open-source project, developed on my spare time. Any contribution, suggestion, feedback or bug report is welcome.
12 | To suggest improvements, report a bug or any issue, please use the issue reporting page, providing all the information and files to reproduce the problem.
13 | If possible please join the debugging output of olefile. For this, launch the following command :
14 | olefile.py -d -c file >debug.txt
15 | You may also contact the author directly to provide feedback.
16 | The code is available in a Mercurial repository on Bitbucket. You may use it to submit enhancements using forks and pull requests.
17 |
18 | olefile documentation
19 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/doc/Contribute.md:
--------------------------------------------------------------------------------
1 | How to Suggest Improvements, Report Issues or Contribute
2 | ========================================================
3 |
4 | This is a personal open-source project, developed on my spare time. Any contribution, suggestion, feedback or bug report is welcome.
5 |
6 | To **suggest improvements, report a bug or any issue**, please use the [issue reporting page](https://bitbucket.org/decalage/olefileio_pl/issues?status=new&status=open), providing all the information and files to reproduce the problem.
7 |
8 | If possible please join the debugging output of olefile. For this, launch the following command :
9 |
10 | :::text
11 | olefile.py -d -c file >debug.txt
12 |
13 |
14 | You may also [contact the author](http://decalage.info/contact) directly to **provide feedback**.
15 |
16 | The code is available in [a Mercurial repository on Bitbucket](https://bitbucket.org/decalage/olefileio_pl). You may use it to **submit enhancements** using forks and pull requests.
17 |
18 | --------------------------------------------------------------------------
19 |
20 | olefile documentation
21 | ---------------------
22 |
23 | - [[Home]]
24 | - [[License]]
25 | - [[Install]]
26 | - [[Contribute]], Suggest Improvements or Report Issues
27 | - [[OLE_Overview]]
28 | - [[API]] and Usage
29 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/doc/Install.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | How to Download and Install olefile
11 | Pre-requisites
12 | olefile requires Python 2.6, 2.7 or 3.x.
13 | For Python 2.5 and older, olefile falls back to an older version (based on OleFileIO_PL 0.26) which might not contain all the enhancements implemented in olefile.
14 | Download and Install
15 | To use olefile with other Python applications or your own scripts, the simplest solution is to run "pip install olefile" or "easy_install olefile" to download and install the package in one go.
16 | Otherwise you may download/extract the zip archive in a temporary directory and run "python setup.py install".
17 | On Windows you may simply double-click on install.bat.
18 |
19 | olefile documentation
20 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/doc/Install.md:
--------------------------------------------------------------------------------
1 | How to Download and Install olefile
2 | ===================================
3 |
4 | Pre-requisites
5 | --------------
6 |
7 | olefile requires Python 2.6, 2.7 or 3.x.
8 |
9 | For Python 2.5 and older, olefile falls back to an older version (based on OleFileIO_PL 0.26) which might not contain all the enhancements implemented in olefile.
10 |
11 |
12 | Download and Install
13 | --------------------
14 |
15 | To use olefile with other Python applications or your own scripts, the simplest solution is to run "**pip install olefile**" or "**easy_install olefile**" to download and install the package in one go.
16 |
17 | Otherwise you may download/extract the [zip archive](https://bitbucket.org/decalage/olefileio_pl/downloads) in a temporary directory and run "**python setup.py install**".
18 |
19 | On Windows you may simply double-click on **install.bat**.
20 |
21 | --------------------------------------------------------------------------
22 |
23 | olefile documentation
24 | ---------------------
25 |
26 | - [[Home]]
27 | - [[License]]
28 | - [[Install]]
29 | - [[Contribute]], Suggest Improvements or Report Issues
30 | - [[OLE_Overview]]
31 | - [[API]] and Usage
32 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/doc/License.md:
--------------------------------------------------------------------------------
1 | License for olefile
2 | ===================
3 |
4 | olefile (formerly OleFileIO_PL) is copyright (c) 2005-2014 Philippe Lagadec ([http://www.decalage.info](http://www.decalage.info))
5 |
6 | All rights reserved.
7 |
8 | Redistribution and use in source and binary forms, with or without modification,
9 | are permitted provided that the following conditions are met:
10 |
11 | * Redistributions of source code must retain the above copyright notice, this
12 | list of conditions and the following disclaimer.
13 | * Redistributions in binary form must reproduce the above copyright notice,
14 | this list of conditions and the following disclaimer in the documentation
15 | and/or other materials provided with the distribution.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
28 |
29 | ----------
30 |
31 | olefile is based on source code from the OleFileIO module of the Python Imaging Library (PIL) published by Fredrik Lundh under the following license:
32 |
33 | The Python Imaging Library (PIL) is
34 |
35 | - Copyright (c) 1997-2005 by Secret Labs AB
36 | - Copyright (c) 1995-2005 by Fredrik Lundh
37 |
38 | By obtaining, using, and/or copying this software and/or its associated documentation, you agree that you have read, understood, and will comply with the following terms and conditions:
39 |
40 | Permission to use, copy, modify, and distribute this software and its associated documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies, and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Secret Labs AB or the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission.
41 |
42 | SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
43 |
44 | --------------------------------------------------------------------------
45 |
46 | olefile documentation
47 | ---------------------
48 |
49 | - [[Home]]
50 | - [[License]]
51 | - [[Install]]
52 | - [[Contribute]], Suggest Improvements or Report Issues
53 | - [[OLE_Overview]]
54 | - [[API]] and Usage
55 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/doc/OLE_Overview.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | About the structure of OLE files
11 | This page is part of the documentation for olefile. It provides a brief overview of the structure of Microsoft OLE2 files (also called Structured Storage, Compound File Binary Format or Compound Document File Format), such as Microsoft Office 97-2003 documents, Image Composer and FlashPix files, Outlook messages, StickyNotes, several Microscopy file formats, McAfee antivirus quarantine files, etc.
12 | An OLE file can be seen as a mini file system or a Zip archive: It contains streams of data that look like files embedded within the OLE file. Each stream has a name. For example, the main stream of a MS Word document containing its text is named "WordDocument".
13 | An OLE file can also contain storages. A storage is a folder that contains streams or other storages. For example, a MS Word document with VBA macros has a storage called "Macros".
14 | Special streams can contain properties. A property is a specific value that can be used to store information such as the metadata of a document (title, author, creation date, etc). Property stream names usually start with the character '05'.
15 | For example, a typical MS Word document may look like this:
16 |
19 | Go to the API page to see how to use all olefile features to parse OLE files.
20 |
21 | olefile documentation
22 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/doc/OLE_Overview.md:
--------------------------------------------------------------------------------
1 | About the structure of OLE files
2 | ================================
3 |
4 | This page is part of the documentation for [olefile](https://bitbucket.org/decalage/olefileio_pl/wiki). It provides a brief overview of the structure of [Microsoft OLE2 files (also called Structured Storage, Compound File Binary Format or Compound Document File Format)](http://en.wikipedia.org/wiki/Compound_File_Binary_Format), such as Microsoft Office 97-2003 documents, Image Composer and FlashPix files, Outlook messages, StickyNotes, several Microscopy file formats, McAfee antivirus quarantine files, etc.
5 |
6 | An OLE file can be seen as a mini file system or a Zip archive: It contains **streams** of data that look like files embedded within the OLE file. Each stream has a name. For example, the main stream of a MS Word document containing its text is named "WordDocument".
7 |
8 | An OLE file can also contain **storages**. A storage is a folder that contains streams or other storages. For example, a MS Word document with VBA macros has a storage called "Macros".
9 |
10 | Special streams can contain **properties**. A property is a specific value that can be used to store information such as the metadata of a document (title, author, creation date, etc). Property stream names usually start with the character '\x05'.
11 |
12 | For example, a typical MS Word document may look like this:
13 |
14 | 
15 |
16 | Go to the [[API]] page to see how to use all olefile features to parse OLE files.
17 |
18 |
19 | --------------------------------------------------------------------------
20 |
21 | olefile documentation
22 | ---------------------
23 |
24 | - [[Home]]
25 | - [[License]]
26 | - [[Install]]
27 | - [[Contribute]], Suggest Improvements or Report Issues
28 | - [[OLE_Overview]]
29 | - [[API]] and Usage
30 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/olefile/doc/OLE_VBA_sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/oletools/thirdparty/olefile/doc/OLE_VBA_sample.png
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/prettytable/COPYING:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2009-2013 Luke Maurits
2 | # All rights reserved.
3 | # With contributions from:
4 | # * Chris Clark
5 | # * Christoph Robbert
6 | # * Klein Stephane
7 | # * "maartendb"
8 | #
9 | # Redistribution and use in source and binary forms, with or without
10 | # modification, are permitted provided that the following conditions are met:
11 | #
12 | # * Redistributions of source code must retain the above copyright notice,
13 | # this list of conditions and the following disclaimer.
14 | # * Redistributions in binary form must reproduce the above copyright notice,
15 | # this list of conditions and the following disclaimer in the documentation
16 | # and/or other materials provided with the distribution.
17 | # * The name of the author may not be used to endorse or promote products
18 | # derived from this software without specific prior written permission.
19 | #
20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | # POSSIBILITY OF SUCH DAMAGE.
31 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/prettytable/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/oletools/thirdparty/prettytable/__init__.py
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/xglob/LICENSE.txt:
--------------------------------------------------------------------------------
1 | LICENSE:
2 |
3 | xglob is copyright (c) 2013-2015, Philippe Lagadec (http://www.decalage.info)
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without modification,
7 | are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 | * Redistributions in binary form must reproduce the above copyright notice,
12 | this list of conditions and the following disclaimer in the documentation
13 | and/or other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/xglob/__init__.py:
--------------------------------------------------------------------------------
1 | from .xglob import *
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/xxxswf/LICENSE.txt:
--------------------------------------------------------------------------------
1 | xxxswf.py is published by Alexander Hanel on
2 | http://hooked-on-mnemonics.blogspot.nl/2011/12/xxxswfpy.html
3 | without explicit license.
--------------------------------------------------------------------------------
/src/utils/oletools/thirdparty/xxxswf/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/oletools/thirdparty/xxxswf/__init__.py
--------------------------------------------------------------------------------
/src/utils/ordlookup/__init__.py:
--------------------------------------------------------------------------------
1 | import ws2_32
2 | import oleaut32
3 |
4 | '''
5 | A small module for keeping a database of ordinal to symbol
6 | mappings for DLLs which frequently get linked without symbolic
7 | infoz.
8 | '''
9 |
10 | ords = {
11 | 'ws2_32.dll':ws2_32.ord_names,
12 | 'wsock32.dll':ws2_32.ord_names,
13 | 'oleaut32.dll':oleaut32.ord_names,
14 | }
15 |
16 | def ordLookup(libname, ord, make_name=False):
17 | '''
18 | Lookup a name for the given ordinal if it's in our
19 | database.
20 | '''
21 | names = ords.get(libname.lower())
22 | if names == None:
23 | if make_name is True:
24 | return 'ord%d' % ord
25 | return None
26 | name = names.get(ord)
27 | if name == None:
28 | return 'ord%d' % ord
29 | return name
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/utils/ordlookup/ws2_32.py:
--------------------------------------------------------------------------------
1 |
2 | ord_names = {
3 | 1:'accept',
4 | 2:'bind',
5 | 3:'closesocket',
6 | 4:'connect',
7 | 5:'getpeername',
8 | 6:'getsockname',
9 | 7:'getsockopt',
10 | 8:'htonl',
11 | 9:'htons',
12 | 10:'ioctlsocket',
13 | 11:'inet_addr',
14 | 12:'inet_ntoa',
15 | 13:'listen',
16 | 14:'ntohl',
17 | 15:'ntohs',
18 | 16:'recv',
19 | 17:'recvfrom',
20 | 18:'select',
21 | 19:'send',
22 | 20:'sendto',
23 | 21:'setsockopt',
24 | 22:'shutdown',
25 | 23:'socket',
26 | 24:'GetAddrInfoW',
27 | 25:'GetNameInfoW',
28 | 26:'WSApSetPostRoutine',
29 | 27:'FreeAddrInfoW',
30 | 28:'WPUCompleteOverlappedRequest',
31 | 29:'WSAAccept',
32 | 30:'WSAAddressToStringA',
33 | 31:'WSAAddressToStringW',
34 | 32:'WSACloseEvent',
35 | 33:'WSAConnect',
36 | 34:'WSACreateEvent',
37 | 35:'WSADuplicateSocketA',
38 | 36:'WSADuplicateSocketW',
39 | 37:'WSAEnumNameSpaceProvidersA',
40 | 38:'WSAEnumNameSpaceProvidersW',
41 | 39:'WSAEnumNetworkEvents',
42 | 40:'WSAEnumProtocolsA',
43 | 41:'WSAEnumProtocolsW',
44 | 42:'WSAEventSelect',
45 | 43:'WSAGetOverlappedResult',
46 | 44:'WSAGetQOSByName',
47 | 45:'WSAGetServiceClassInfoA',
48 | 46:'WSAGetServiceClassInfoW',
49 | 47:'WSAGetServiceClassNameByClassIdA',
50 | 48:'WSAGetServiceClassNameByClassIdW',
51 | 49:'WSAHtonl',
52 | 50:'WSAHtons',
53 | 51:'gethostbyaddr',
54 | 52:'gethostbyname',
55 | 53:'getprotobyname',
56 | 54:'getprotobynumber',
57 | 55:'getservbyname',
58 | 56:'getservbyport',
59 | 57:'gethostname',
60 | 58:'WSAInstallServiceClassA',
61 | 59:'WSAInstallServiceClassW',
62 | 60:'WSAIoctl',
63 | 61:'WSAJoinLeaf',
64 | 62:'WSALookupServiceBeginA',
65 | 63:'WSALookupServiceBeginW',
66 | 64:'WSALookupServiceEnd',
67 | 65:'WSALookupServiceNextA',
68 | 66:'WSALookupServiceNextW',
69 | 67:'WSANSPIoctl',
70 | 68:'WSANtohl',
71 | 69:'WSANtohs',
72 | 70:'WSAProviderConfigChange',
73 | 71:'WSARecv',
74 | 72:'WSARecvDisconnect',
75 | 73:'WSARecvFrom',
76 | 74:'WSARemoveServiceClass',
77 | 75:'WSAResetEvent',
78 | 76:'WSASend',
79 | 77:'WSASendDisconnect',
80 | 78:'WSASendTo',
81 | 79:'WSASetEvent',
82 | 80:'WSASetServiceA',
83 | 81:'WSASetServiceW',
84 | 82:'WSASocketA',
85 | 83:'WSASocketW',
86 | 84:'WSAStringToAddressA',
87 | 85:'WSAStringToAddressW',
88 | 86:'WSAWaitForMultipleEvents',
89 | 87:'WSCDeinstallProvider',
90 | 88:'WSCEnableNSProvider',
91 | 89:'WSCEnumProtocols',
92 | 90:'WSCGetProviderPath',
93 | 91:'WSCInstallNameSpace',
94 | 92:'WSCInstallProvider',
95 | 93:'WSCUnInstallNameSpace',
96 | 94:'WSCUpdateProvider',
97 | 95:'WSCWriteNameSpaceOrder',
98 | 96:'WSCWriteProviderOrder',
99 | 97:'freeaddrinfo',
100 | 98:'getaddrinfo',
101 | 99:'getnameinfo',
102 | 101:'WSAAsyncSelect',
103 | 102:'WSAAsyncGetHostByAddr',
104 | 103:'WSAAsyncGetHostByName',
105 | 104:'WSAAsyncGetProtoByNumber',
106 | 105:'WSAAsyncGetProtoByName',
107 | 106:'WSAAsyncGetServByPort',
108 | 107:'WSAAsyncGetServByName',
109 | 108:'WSACancelAsyncRequest',
110 | 109:'WSASetBlockingHook',
111 | 110:'WSAUnhookBlockingHook',
112 | 111:'WSAGetLastError',
113 | 112:'WSASetLastError',
114 | 113:'WSACancelBlockingCall',
115 | 114:'WSAIsBlocking',
116 | 115:'WSAStartup',
117 | 116:'WSACleanup',
118 | 151:'__WSAFDIsSet',
119 | 500:'WEP',
120 | }
121 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/__init__.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | # http://www.python.org/dev/peps/pep-0396/
4 | __version__ = '0.1.4'
5 |
6 | if sys.version_info[:2] < (2, 4):
7 | raise RuntimeError('PyASN1 requires Python 2.4 or later')
8 |
9 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/codec/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is necessary to make this directory a package.
2 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/codec/ber/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is necessary to make this directory a package.
2 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/codec/ber/eoo.py:
--------------------------------------------------------------------------------
1 | from utils.pyasn1.type import base, tag
2 |
3 | class EndOfOctets(base.AbstractSimpleAsn1Item):
4 | defaultValue = 0
5 | tagSet = tag.initTagSet(
6 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x00)
7 | )
8 | endOfOctets = EndOfOctets()
9 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/codec/cer/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is necessary to make this directory a package.
2 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/codec/cer/decoder.py:
--------------------------------------------------------------------------------
1 | # CER decoder
2 | from utils.pyasn1.type import univ
3 | from utils.pyasn1.codec.ber import decoder
4 | from utils.pyasn1.compat.octets import oct2int
5 | from utils.pyasn1 import error
6 |
7 | class BooleanDecoder(decoder.AbstractSimpleDecoder):
8 | protoComponent = univ.Boolean(0)
9 | def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
10 | state, decodeFun, substrateFun):
11 | head, tail = substrate[:length], substrate[length:]
12 | if not head:
13 | raise error.PyAsn1Error('Empty substrate')
14 | byte = oct2int(head[0])
15 | # CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while
16 | # BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1
17 | # in http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
18 | if byte == 0xff:
19 | value = 1
20 | elif byte == 0x00:
21 | value = 0
22 | else:
23 | raise error.PyAsn1Error('Boolean CER violation: %s' % byte)
24 | return self._createComponent(asn1Spec, tagSet, value), tail
25 |
26 | tagMap = decoder.tagMap.copy()
27 | tagMap.update({
28 | univ.Boolean.tagSet: BooleanDecoder()
29 | })
30 |
31 | typeMap = decoder.typeMap
32 |
33 | class Decoder(decoder.Decoder): pass
34 |
35 | decode = Decoder(tagMap, decoder.typeMap)
36 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/codec/cer/encoder.py:
--------------------------------------------------------------------------------
1 | # CER encoder
2 | from utils.pyasn1.type import univ
3 | from utils.pyasn1.codec.ber import encoder
4 | from utils.pyasn1.compat.octets import int2oct, null
5 |
6 | class BooleanEncoder(encoder.IntegerEncoder):
7 | def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
8 | if client == 0:
9 | substrate = int2oct(0)
10 | else:
11 | substrate = int2oct(255)
12 | return substrate, 0
13 |
14 | class BitStringEncoder(encoder.BitStringEncoder):
15 | def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
16 | return encoder.BitStringEncoder.encodeValue(
17 | self, encodeFun, client, defMode, 1000
18 | )
19 |
20 | class OctetStringEncoder(encoder.OctetStringEncoder):
21 | def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
22 | return encoder.OctetStringEncoder.encodeValue(
23 | self, encodeFun, client, defMode, 1000
24 | )
25 |
26 | # specialized RealEncoder here
27 | # specialized GeneralStringEncoder here
28 | # specialized GeneralizedTimeEncoder here
29 | # specialized UTCTimeEncoder here
30 |
31 | class SetOfEncoder(encoder.SequenceOfEncoder):
32 | def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
33 | if isinstance(client, univ.SequenceAndSetBase):
34 | client.setDefaultComponents()
35 | client.verifySizeSpec()
36 | substrate = null; idx = len(client)
37 | # This is certainly a hack but how else do I distinguish SetOf
38 | # from Set if they have the same tags&constraints?
39 | if isinstance(client, univ.SequenceAndSetBase):
40 | # Set
41 | comps = []
42 | while idx > 0:
43 | idx = idx - 1
44 | if client[idx] is None: # Optional component
45 | continue
46 | if client.getDefaultComponentByPosition(idx) == client[idx]:
47 | continue
48 | comps.append(client[idx])
49 | comps.sort(key=lambda x: isinstance(x, univ.Choice) and \
50 | x.getMinTagSet() or x.getTagSet())
51 | for c in comps:
52 | substrate += encodeFun(c, defMode, maxChunkSize)
53 | else:
54 | # SetOf
55 | compSubs = []
56 | while idx > 0:
57 | idx = idx - 1
58 | compSubs.append(
59 | encodeFun(client[idx], defMode, maxChunkSize)
60 | )
61 | compSubs.sort() # perhaps padding's not needed
62 | substrate = null
63 | for compSub in compSubs:
64 | substrate += compSub
65 | return substrate, 1
66 |
67 | tagMap = encoder.tagMap.copy()
68 | tagMap.update({
69 | univ.Boolean.tagSet: BooleanEncoder(),
70 | univ.BitString.tagSet: BitStringEncoder(),
71 | univ.OctetString.tagSet: OctetStringEncoder(),
72 | univ.SetOf().tagSet: SetOfEncoder() # conflcts with Set
73 | })
74 |
75 | typeMap = encoder.typeMap.copy()
76 | typeMap.update({
77 | univ.Set.typeId: SetOfEncoder(),
78 | univ.SetOf.typeId: SetOfEncoder()
79 | })
80 |
81 | class Encoder(encoder.Encoder):
82 | def __call__(self, client, defMode=0, maxChunkSize=0):
83 | return encoder.Encoder.__call__(self, client, defMode, maxChunkSize)
84 |
85 | encode = Encoder(tagMap, typeMap)
86 |
87 | # EncoderFactory queries class instance and builds a map of tags -> encoders
88 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/codec/der/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is necessary to make this directory a package.
2 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/codec/der/decoder.py:
--------------------------------------------------------------------------------
1 | # DER decoder
2 | from utils.pyasn1.type import univ
3 | from utils.pyasn1.codec.cer import decoder
4 |
5 | tagMap = decoder.tagMap
6 | typeMap = decoder.typeMap
7 | Decoder = decoder.Decoder
8 |
9 | decode = Decoder(tagMap, typeMap)
10 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/codec/der/encoder.py:
--------------------------------------------------------------------------------
1 | # DER encoder
2 | from utils.pyasn1.type import univ
3 | from utils.pyasn1.codec.cer import encoder
4 |
5 | class SetOfEncoder(encoder.SetOfEncoder):
6 | def _cmpSetComponents(self, c1, c2):
7 | tagSet1 = isinstance(c1, univ.Choice) and \
8 | c1.getEffectiveTagSet() or c1.getTagSet()
9 | tagSet2 = isinstance(c2, univ.Choice) and \
10 | c2.getEffectiveTagSet() or c2.getTagSet()
11 | return cmp(tagSet1, tagSet2)
12 |
13 | tagMap = encoder.tagMap.copy()
14 | tagMap.update({
15 | # Overload CER encodrs with BER ones (a bit hackerish XXX)
16 | univ.BitString.tagSet: encoder.encoder.BitStringEncoder(),
17 | univ.OctetString.tagSet: encoder.encoder.OctetStringEncoder(),
18 | # Set & SetOf have same tags
19 | univ.SetOf().tagSet: SetOfEncoder()
20 | })
21 |
22 | typeMap = encoder.typeMap
23 |
24 | class Encoder(encoder.Encoder):
25 | def __call__(self, client, defMode=1, maxChunkSize=0):
26 | return encoder.Encoder.__call__(self, client, defMode, maxChunkSize)
27 |
28 | encode = Encoder(tagMap, typeMap)
29 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/compat/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is necessary to make this directory a package.
2 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/compat/octets.py:
--------------------------------------------------------------------------------
1 | from sys import version_info
2 |
3 | if version_info[0] <= 2:
4 | int2oct = chr
5 | ints2octs = lambda s: ''.join([ int2oct(x) for x in s ])
6 | null = ''
7 | oct2int = ord
8 | octs2ints = lambda s: [ oct2int(x) for x in s ]
9 | str2octs = lambda x: x
10 | octs2str = lambda x: x
11 | isOctetsType = lambda s: isinstance(s, str)
12 | else:
13 | ints2octs = bytes
14 | int2oct = lambda x: ints2octs((x,))
15 | null = ints2octs()
16 | oct2int = lambda x: x
17 | octs2ints = lambda s: [ x for x in s ]
18 | str2octs = lambda x: x.encode()
19 | octs2str = lambda x: x.decode()
20 | isOctetsType = lambda s: isinstance(s, bytes)
21 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/debug.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from utils.pyasn1.compat.octets import octs2ints
3 | from utils.pyasn1 import error
4 |
5 | flagNone = 0x0000
6 | flagEncoder = 0x0001
7 | flagDecoder = 0x0002
8 | flagAll = 0xffff
9 |
10 | flagMap = {
11 | 'encoder': flagEncoder,
12 | 'decoder': flagDecoder,
13 | 'all': flagAll
14 | }
15 |
16 | class Debug:
17 | defaultPrinter = sys.stderr.write
18 | def __init__(self, *flags):
19 | self._flags = flagNone
20 | self._printer = self.defaultPrinter
21 | for f in flags:
22 | if f not in flagMap:
23 | raise error.PyAsn1Error('bad debug flag %s' % (f,))
24 | self._flags = self._flags | flagMap[f]
25 | self('debug category %s enabled' % f)
26 |
27 | def __str__(self):
28 | return 'logger %s, flags %x' % (self._printer, self._flags)
29 |
30 | def __call__(self, msg):
31 | self._printer('DBG: %s\n' % msg)
32 |
33 | def __and__(self, flag):
34 | return self._flags & flag
35 |
36 | def __rand__(self, flag):
37 | return flag & self._flags
38 |
39 | logger = 0
40 |
41 | def setLogger(l):
42 | global logger
43 | logger = l
44 |
45 | def hexdump(octets):
46 | return ' '.join(
47 | [ '%s%.2X' % (n%16 == 0 and ('\n%.5d: ' % n) or '', x)
48 | for n,x in zip(range(len(octets)), octs2ints(octets)) ]
49 | )
50 |
51 | class Scope:
52 | def __init__(self):
53 | self._list = []
54 |
55 | def __str__(self): return '.'.join(self._list)
56 |
57 | def push(self, token):
58 | self._list.append(token)
59 |
60 | def pop(self):
61 | return self._list.pop()
62 |
63 | scope = Scope()
64 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/dn.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Copyright 2011 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | # Author: caronni@google.com (Germano Caronni)
18 |
19 | """dn converts ASN.1 Distinguished Names to strings.
20 |
21 | TODO(user): TraverseRdn should build a better string representation,
22 | see comments below. RFC2253 provides the right way to do this. Instead of
23 | returning a dict, return a string.
24 | May also want an inverse function, parsing a string into an RDN sequence.
25 | """
26 |
27 | #try:
28 | from utils.pyasn1.codec.ber import decoder
29 | #except ImportError:
30 | # raise ImportError, 'pyasn1 is required to run this program : http://pyasn1.sourceforge.net/ or sudo apt-get install python-pyasn1'
31 |
32 | class DistinguishedName(object):
33 | """Container for relevant OIDs and static conversion methods."""
34 |
35 | # I want the formatting to make sense and be readable, really.
36 | # pylint: disable-msg=C6007
37 | OIDs = {
38 | (2, 5, 4, 3) : 'CN', # common name
39 | (2, 5, 4, 6) : 'C', # country
40 | (2, 5, 4, 7) : 'L', # locality
41 | (2, 5, 4, 8) : 'ST', # stateOrProvince
42 | (2, 5, 4, 10) : 'O', # organization
43 | (2, 5, 4, 11) : 'OU', # organizationalUnit
44 | (0, 9, 2342, 19200300, 100, 1, 25) : 'DC', # domainComponent
45 | (1, 2, 840, 113549, 1, 9, 1) : 'EMAIL', # emailaddress
46 | }
47 | # pylint: enable-msg=C6007
48 |
49 | @staticmethod
50 | def OidToName(oid):
51 | return DistinguishedName.OIDs.get(oid, str(oid))
52 |
53 | @staticmethod
54 | def TraverseRdn(rdn):
55 | """Traverses RDN structure and returns string encoding of the DN.
56 |
57 | Args:
58 | rdn: ASN.1 SET (or SEQUENCE) containing RDNs (relative distinguished
59 | names), as identified by type / value pairs. A typical input would
60 | be of type X.509 RelativeDistinguishedName.
61 |
62 | Returns:
63 | A dict representing the Distinguished Name.
64 | """
65 | val = dict()
66 | for n in rdn:
67 | # Note that this does not work for e.g. DC which is present
68 | # multiple times.
69 | # For a real DN parser, make sure to follow the spec in regards
70 | # to multiple occurence of a field in subsequent RDNs, maintaining
71 | # original ordering etc.
72 | # TODO(user): What about elements other than [0]??
73 | name = DistinguishedName.OidToName(n[0]['type'])
74 | value = decoder.decode(n[0]['value'])
75 | if name in val:
76 | val[name] = str(value[0]) + ', ' + val.get(name, '')
77 | else:
78 | val[name] = str(value[0])
79 | return val
80 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/error.py:
--------------------------------------------------------------------------------
1 | class PyAsn1Error(Exception): pass
2 | class ValueConstraintError(PyAsn1Error): pass
3 | class SubstrateUnderrunError(PyAsn1Error): pass
4 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/oids.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Copyright 2011 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | # Author: caronni@google.com (Germano Caronni)
18 |
19 | """ASN.1 OIDs mappings to parser classes or strings, where there is no class."""
20 |
21 | import hashlib
22 |
23 | import pkcs7
24 | import spc
25 |
26 |
27 | # I want the formatting to make sense and be readable, really.
28 | # pylint: disable-msg=C6006,C6007
29 | OID_TO_CLASS = {
30 | (1, 2, 840, 113549, 1, 7, 1) : 'PKCS#7 Data',
31 | (1, 2, 840, 113549, 1, 7, 2) : pkcs7.SignedData,
32 | (1, 2, 840, 113549, 2, 5) : hashlib.md5,
33 | (1, 3, 14, 3, 2, 26) : hashlib.sha1,
34 | (1, 3, 6, 1, 4, 1, 311, 2, 1, 4) : spc.SpcIndirectDataContent,
35 | (1, 2, 840, 113549, 1, 9, 3) : pkcs7.ContentType,
36 | (1, 2, 840, 113549, 1, 9, 4) : pkcs7.DigestInfo,
37 | (1, 3, 6, 1, 4, 1, 311, 2, 1, 12) : spc.SpcSpOpusInfo,
38 | (1, 2, 840, 113549, 1, 9, 6) : pkcs7.CountersignInfo, # 'RSA_counterSign'
39 | (1, 2, 840, 113549, 1, 9, 5) : pkcs7.SigningTime,
40 | }
41 |
42 | OID_TO_PUBKEY = {
43 | (1, 2, 840, 113549, 1, 1, 1) : 'rsa',
44 | (1, 2, 840, 113549, 1, 1, 5) : 'rsa-sha1',
45 | (1, 2, 840, 10040, 4, 1) : 'dsa',
46 | }
47 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/spc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Copyright 2011 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | # Author: caronni@google.com (Germano Caronni)
18 |
19 | """Authenticode-specific ASN.1 data structures."""
20 |
21 | try:
22 | from utils.pyasn1.type import char
23 | from utils.pyasn1.type import namedtype
24 | from utils.pyasn1.type import tag
25 | from utils.pyasn1.type import univ
26 | except ImportError:
27 | raise ImportError, 'pyasn1 is required to run this program : http://pyasn1.sourceforge.net/ or sudo apt-get install python-pyasn1'
28 |
29 | from pkcs7 import DigestInfo
30 | import x509
31 |
32 |
33 | class SpcAttributeTypeAndOptionalValue(univ.Sequence):
34 | componentType = namedtype.NamedTypes(
35 | namedtype.NamedType('type', x509.AttributeType()),
36 | namedtype.OptionalNamedType('value', x509.AttributeValue()))
37 |
38 |
39 | class SpcIndirectDataContent(univ.Sequence):
40 | componentType = namedtype.NamedTypes(
41 | namedtype.NamedType('data', SpcAttributeTypeAndOptionalValue()),
42 | namedtype.NamedType('messageDigest', DigestInfo()))
43 |
44 |
45 | class SpcUuid(univ.OctetString):
46 | pass
47 |
48 |
49 | class SpcSerializedObject(univ.Sequence):
50 | componentType = namedtype.NamedTypes(
51 | namedtype.NamedType('classId', SpcUuid()),
52 | namedtype.NamedType('serializedData', univ.OctetString()))
53 |
54 |
55 | class SpcString(univ.Choice):
56 | componentType = namedtype.NamedTypes(
57 | namedtype.NamedType('unicode', char.BMPString().subtype(
58 | implicitTag=tag.Tag(tag.tagClassContext,
59 | tag.tagFormatConstructed, 0))),
60 | namedtype.NamedType('ascii', char.IA5String().subtype(
61 | implicitTag=tag.Tag(tag.tagClassContext,
62 | tag.tagFormatConstructed, 1))))
63 |
64 |
65 | class SpcLink(univ.Choice):
66 | """According to Authenticode specification."""
67 | componentType = namedtype.NamedTypes(
68 | namedtype.NamedType('url', char.IA5String().subtype(
69 | implicitTag=tag.Tag(tag.tagClassContext,
70 | tag.tagFormatConstructed, 0))),
71 | namedtype.NamedType('moniker', SpcSerializedObject().subtype(
72 | implicitTag=tag.Tag(tag.tagClassContext,
73 | tag.tagFormatConstructed, 1))),
74 | namedtype.NamedType('file', SpcString().subtype(
75 | explicitTag=tag.Tag(tag.tagClassContext,
76 | tag.tagFormatConstructed, 2))))
77 |
78 |
79 | class SpcSpOpusInfo(univ.Sequence):
80 | componentType = namedtype.NamedTypes(
81 | namedtype.OptionalNamedType('programName', SpcString().subtype(
82 | explicitTag=tag.Tag(tag.tagClassContext,
83 | tag.tagFormatConstructed, 0))),
84 | namedtype.OptionalNamedType('moreInfo', SpcLink().subtype(
85 | explicitTag=tag.Tag(tag.tagClassContext,
86 | tag.tagFormatConstructed, 1))))
87 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/time_test.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Copyright 2012 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | # Author: caronni@google.com (Germano Caronni)
18 |
19 | """Tests for time conversion utility."""
20 |
21 | from utils.pyasn1.type import useful
22 | import time
23 |
24 | import unittest as test
25 | from x509_time import Time
26 |
27 |
28 | class TimeTest(test.TestCase):
29 |
30 | def testConvert(self):
31 | utctime = useful.UTCTime('120614235959Z')
32 | t = Time()
33 | t.setComponentByName('utcTime', utctime)
34 | t_str = time.asctime(time.gmtime(t.ToPythonEpochTime()))
35 | self.assertEquals(t_str, 'Thu Jun 14 23:59:59 2012')
36 |
37 |
38 | def main():
39 | test.main()
40 |
41 | if __name__ == '__main__':
42 | main()
43 |
44 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/type/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is necessary to make this directory a package.
2 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/type/char.py:
--------------------------------------------------------------------------------
1 | # ASN.1 "character string" types
2 | from utils.pyasn1.type import univ, tag
3 |
4 | class UTF8String(univ.OctetString):
5 | tagSet = univ.OctetString.tagSet.tagImplicitly(
6 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
7 | )
8 | encoding = "utf-8"
9 |
10 | class NumericString(univ.OctetString):
11 | tagSet = univ.OctetString.tagSet.tagImplicitly(
12 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 18)
13 | )
14 |
15 | class PrintableString(univ.OctetString):
16 | tagSet = univ.OctetString.tagSet.tagImplicitly(
17 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 19)
18 | )
19 |
20 | class TeletexString(univ.OctetString):
21 | tagSet = univ.OctetString.tagSet.tagImplicitly(
22 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 20)
23 | )
24 |
25 |
26 | class VideotexString(univ.OctetString):
27 | tagSet = univ.OctetString.tagSet.tagImplicitly(
28 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 21)
29 | )
30 |
31 | class IA5String(univ.OctetString):
32 | tagSet = univ.OctetString.tagSet.tagImplicitly(
33 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 22)
34 | )
35 |
36 | class GraphicString(univ.OctetString):
37 | tagSet = univ.OctetString.tagSet.tagImplicitly(
38 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 25)
39 | )
40 |
41 | class VisibleString(univ.OctetString):
42 | tagSet = univ.OctetString.tagSet.tagImplicitly(
43 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 26)
44 | )
45 |
46 | class GeneralString(univ.OctetString):
47 | tagSet = univ.OctetString.tagSet.tagImplicitly(
48 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 27)
49 | )
50 |
51 | class UniversalString(univ.OctetString):
52 | tagSet = univ.OctetString.tagSet.tagImplicitly(
53 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 28)
54 | )
55 | encoding = "utf-32-be"
56 |
57 | class BMPString(univ.OctetString):
58 | tagSet = univ.OctetString.tagSet.tagImplicitly(
59 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 30)
60 | )
61 | encoding = "utf-16-be"
62 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/type/error.py:
--------------------------------------------------------------------------------
1 | from utils.pyasn1.error import PyAsn1Error
2 |
3 | class ValueConstraintError(PyAsn1Error): pass
4 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/type/namedval.py:
--------------------------------------------------------------------------------
1 | # ASN.1 named integers
2 | from utils.pyasn1 import error
3 |
4 | __all__ = [ 'NamedValues' ]
5 |
6 | class NamedValues:
7 | def __init__(self, *namedValues):
8 | self.nameToValIdx = {}; self.valToNameIdx = {}
9 | self.namedValues = ()
10 | automaticVal = 1
11 | for namedValue in namedValues:
12 | if isinstance(namedValue, tuple):
13 | name, val = namedValue
14 | else:
15 | name = namedValue
16 | val = automaticVal
17 | if name in self.nameToValIdx:
18 | raise error.PyAsn1Error('Duplicate name %s' % (name,))
19 | self.nameToValIdx[name] = val
20 | if val in self.valToNameIdx:
21 | raise error.PyAsn1Error('Duplicate value %s=%s' % (name, val))
22 | self.valToNameIdx[val] = name
23 | self.namedValues = self.namedValues + ((name, val),)
24 | automaticVal = automaticVal + 1
25 | def __str__(self): return str(self.namedValues)
26 |
27 | def getName(self, value):
28 | if value in self.valToNameIdx:
29 | return self.valToNameIdx[value]
30 |
31 | def getValue(self, name):
32 | if name in self.nameToValIdx:
33 | return self.nameToValIdx[name]
34 |
35 | def __getitem__(self, i): return self.namedValues[i]
36 | def __len__(self): return len(self.namedValues)
37 |
38 | def __add__(self, namedValues):
39 | return self.__class__(*self.namedValues + namedValues)
40 | def __radd__(self, namedValues):
41 | return self.__class__(*namedValues + tuple(self))
42 |
43 | def clone(self, *namedValues):
44 | return self.__class__(*tuple(self) + namedValues)
45 |
46 | # XXX clone/subtype?
47 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/type/tagmap.py:
--------------------------------------------------------------------------------
1 | from utils.pyasn1 import error
2 |
3 | class TagMap:
4 | def __init__(self, posMap={}, negMap={}, defType=None):
5 | self.__posMap = posMap.copy()
6 | self.__negMap = negMap.copy()
7 | self.__defType = defType
8 |
9 | def __contains__(self, tagSet):
10 | return tagSet in self.__posMap or \
11 | self.__defType is not None and tagSet not in self.__negMap
12 |
13 | def __getitem__(self, tagSet):
14 | if tagSet in self.__posMap:
15 | return self.__posMap[tagSet]
16 | elif tagSet in self.__negMap:
17 | raise error.PyAsn1Error('Key in negative map')
18 | elif self.__defType is not None:
19 | return self.__defType
20 | else:
21 | raise KeyError()
22 |
23 | def __repr__(self):
24 | s = '%r/%r' % (self.__posMap, self.__negMap)
25 | if self.__defType is not None:
26 | s = s + '/%r' % (self.__defType,)
27 | return s
28 |
29 | def clone(self, parentType, tagMap, uniq=False):
30 | if self.__defType is not None and tagMap.getDef() is not None:
31 | raise error.PyAsn1Error('Duplicate default value at %s' % (self,))
32 | if tagMap.getDef() is not None:
33 | defType = tagMap.getDef()
34 | else:
35 | defType = self.__defType
36 |
37 | posMap = self.__posMap.copy()
38 | for k in tagMap.getPosMap():
39 | if uniq and k in posMap:
40 | raise error.PyAsn1Error('Duplicate positive key %s' % (k,))
41 | posMap[k] = parentType
42 |
43 | negMap = self.__negMap.copy()
44 | negMap.update(tagMap.getNegMap())
45 |
46 | return self.__class__(
47 | posMap, negMap, defType,
48 | )
49 |
50 | def getPosMap(self): return self.__posMap.copy()
51 | def getNegMap(self): return self.__negMap.copy()
52 | def getDef(self): return self.__defType
53 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/type/useful.py:
--------------------------------------------------------------------------------
1 | # ASN.1 "useful" types
2 | from utils.pyasn1.type import char, tag
3 |
4 | class GeneralizedTime(char.VisibleString):
5 | tagSet = char.VisibleString.tagSet.tagImplicitly(
6 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 24)
7 | )
8 |
9 | class UTCTime(char.VisibleString):
10 | tagSet = char.VisibleString.tagSet.tagImplicitly(
11 | tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 23)
12 | )
13 |
--------------------------------------------------------------------------------
/src/utils/pyasn1/x509_time.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Copyright 2012 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | # Author: caronni@google.com (Germano Caronni)
18 |
19 | """X.509 Time class and utility functions.
20 |
21 | Limited interpretation of ASN.1 time formats,
22 | as specified in RFC2459, section 4.1.2.5
23 | """
24 |
25 | import calendar
26 | import time
27 |
28 |
29 | try:
30 | from utils.pyasn1 import error
31 | from utils.pyasn1.type import namedtype
32 | from utils.pyasn1.type import univ
33 | from utils.pyasn1.type import useful
34 | except ImportError:
35 | raise ImportError, 'pyasn1 is required to run this program : http://pyasn1.sourceforge.net/ or sudo apt-get install python-pyasn1'
36 |
37 | class Time(univ.Choice):
38 | componentType = namedtype.NamedTypes(
39 | namedtype.NamedType('utcTime', useful.UTCTime()),
40 | namedtype.NamedType('generalTime', useful.GeneralizedTime()))
41 |
42 | def ToPythonEpochTime(self):
43 | """Takes a ASN.1 Time choice, and returns seconds since epoch in UTC."""
44 | utc_time = self.getComponentByName('utcTime')
45 | general_time = self.getComponentByName('generalTime')
46 | if utc_time and general_time:
47 | raise error.PyAsn1Error('Both elements of a choice are present.')
48 | if general_time:
49 | format_str = '%Y%m%d%H%M%SZ'
50 | time_str = str(general_time)
51 | else:
52 | format_str = '%y%m%d%H%M%SZ'
53 | time_str = str(utc_time)
54 | time_tpl = time.strptime(time_str, format_str)
55 | return calendar.timegm(time_tpl)
56 |
--------------------------------------------------------------------------------
/src/utils/verifySigs/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/verifySigs/__init__.py
--------------------------------------------------------------------------------
/src/utils/verifySigs/pecoff_blob.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Copyright 2011 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | # Author: caronni@google.com (Germano Caronni)
18 |
19 | """Deal with Microsoft-specific Authenticode data."""
20 |
21 | # Comments and constant names as extracted from pecoff_v8 specs.
22 | # Variable names are also used as defined in the PECOFF specification.
23 | # pylint: disable-msg=C6409
24 |
25 | # Version 1, legacy version of Win_Certificate structure. It is supported
26 | # only for purposes of verifying legacy Authenticode signatures.
27 | WIN_CERT_REVISION_1_0 = 0x100
28 |
29 | # Version 2 is the current version of the Win_Certificate structure.
30 | WIN_CERT_REVISION_2_0 = 0x200
31 |
32 | # Only type PKCS is supported by the pecoff specification.
33 | WIN_CERT_TYPE_X509 = 1
34 | WIN_CERT_TYPE_PKCS_SIGNED_DATA = 2
35 | WIN_CERT_TYPE_RESERVED_1 = 3
36 | WIN_CERT_TYPE_TS_STACK_SIGNED = 4
37 |
38 |
39 | class PecoffBlob(object):
40 | """Encapsulating class for Microsoft-specific Authenticode data.
41 |
42 | As defined in the PECOFF (v8) and Authenticode specifications.
43 | This is data as it is extracted from the signature_data field by
44 | the fingerprinter.
45 | """
46 |
47 | def __init__(self, signed_data_tuple):
48 | self._wRevision = signed_data_tuple[0]
49 | self._wCertificateType = signed_data_tuple[1]
50 | self._bCertificate = signed_data_tuple[2]
51 |
52 | if self._wRevision != WIN_CERT_REVISION_2_0:
53 | raise RuntimeError("Unknown revision %#x." % self._wRevision)
54 | if self._wCertificateType != WIN_CERT_TYPE_PKCS_SIGNED_DATA:
55 | raise RuntimeError("Unknown cert type %#x." % self._wCertificateType)
56 |
57 | def getCertificateBlob(self):
58 | return self._bCertificate
59 |
--------------------------------------------------------------------------------
/src/utils/verifySigs/sigcheck.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/src/utils/verifySigs/sigcheck.exe
--------------------------------------------------------------------------------
/versions/build.number:
--------------------------------------------------------------------------------
1 | #Build Number for ANT. Do not edit!
2 | #Fri Mar 21 11:12:00 CET 2014
3 | build.number=0
4 |
--------------------------------------------------------------------------------
/versions/ragpicker_v0.06.0_remnux.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robbyFux/Ragpicker/77d68ff3a13851ed4c256635f0673a4c2a84ef51/versions/ragpicker_v0.06.0_remnux.zip
--------------------------------------------------------------------------------
/versions/ragpicker_version.json:
--------------------------------------------------------------------------------
1 | {
2 | "ragpicker.build.major.number":"0",
3 | "ragpicker.build.minor.number":"06",
4 | "ragpicker.build.number":"00",
5 | "ragpicker.build.date":"19.05.2014 00:00"
6 | }
--------------------------------------------------------------------------------