├── .gitignore
├── AFF4
├── __init__.py
└── aff4.py
├── AdamBridge
├── README.md
├── __init__.py
├── linux_xwindows.py
└── ndispktscan.py
├── AleksanderOsterud
├── Capabilities-example.pdf
├── MemoryDecompression.zip
└── MemoryDecompressionV09 User Guide.pdf
├── AlessandroDeVito
├── README.md
├── __init__.py
├── chrome_ragamuffin.py
├── libchrome_5803029110.py
└── libchrome_600311290.py
├── AlizHammond
├── README.md
└── gargoyle.py
├── AndreasSchuster
├── __init__.py
└── poisonivy.py
├── AndrewCook
├── __init__.py
└── saveconfig.py
├── AngeloMirabella
└── README.md
├── BlaineStancill
└── README.md
├── CemGurkok
├── README.md
├── __init__.py
└── bitcoin.py
├── CesarePizzi
├── README.md
├── Volatility_Plugin_Powershell.pdf
└── powersh.py
├── Citronneur
├── README.md
└── wnf.py
├── CsabaBarta
├── README.md
├── __init__.py
├── baseline.py
├── indx.py
├── logfile.py
├── malprocfind.py
└── usnjrnl.py
├── DatQuoc
├── LinuxFirefox.py
├── Readme.pdf
└── __init__.py
├── DaveLasalle
├── README.md
├── __init__.py
├── apihooksdeep.py
├── chromehistory.py
├── firefoxhistory.py
├── idxparser.py
├── malfinddeep.py
├── prefetch.py
├── sqlite_help.py
├── ssdeepscan.py
├── trustrecords.py
└── uninstallinfo.py
├── DavidQuesada
├── README.md
└── dash_volatility.xml
├── DimaPshoul
├── DimaPshoul - Volatility Contest 2016 Submission.pdf
├── README.md
├── __init__.py
├── callstacks.py
├── malfofind.py
└── malthfind.py
├── ESET_Browserhooks
├── README.md
├── __init__.py
├── browserhooks.py
└── browserhooks_documentation.pdf
├── EWF
├── __init__.py
└── ewf.py
├── ElmarNabigaev
├── README.md
└── vmtools.py
├── EnumFunc
├── __init__.py
└── enumfunc.py
├── FabienPerigaud
├── README.md
├── __init__.py
└── plugx.py
├── FabioPagani
├── README.md
└── volc.zip
├── FrancescoPicasso
├── README.md
├── __init__.py
└── mimikatz.py
├── FrankBlock
├── README.md
├── __init__.py
├── heap_analysis.py
├── keepassx.py
├── man.txt
└── zsh.py
├── GlennEdwards
├── README.md
├── __init__.py
└── system_info.py
├── JPCERT
├── LICENSE.txt
├── README.md
├── __init__.py
└── apt17scan.py
├── JamaalSpeights
├── README.md
├── __init__.py
└── msdecompress.py
├── JamesHall_KevinBreen
├── README.md
├── __init__.py
└── usbstor.py
├── JavierVallejo
├── README.md
├── __init__.py
└── symbolizemod.py
├── JeffBryner
├── README.md
├── __init__.py
├── facebook.py
└── twitter.py
├── JoeGreenwood
├── README.md
├── __init__.py
└── attributeht.py
├── KSLGroup_Threadmap
├── README.md
├── __init__.py
├── threadmap documentation.pdf
└── threadmap.py
├── KevinBreen
├── README.md
├── __init__.py
└── lastpass.py
├── KudelskiSecurity
├── README.md
├── __init__.py
└── dyrescan.py
├── LoicJaquemet
├── README.md
├── __init__.py
└── vol_haystack.py
├── LorenzLiebler
├── 2018_volcon_liebler_pub.pdf
└── apx_maps.py
├── MarianoGraziano
├── README.md
├── __init__.py
└── kstackps.py
├── MichaelBrown
├── HOW_IT_WORKS.md
├── README 2.md
├── README.md
├── TODO
├── TUTORIAL.md
├── __init__.py
├── analysis
│ ├── README.md
│ ├── create_test_db.py
│ └── data
│ │ ├── firefox_recovered_places.csv
│ │ ├── firefox_tables.csv
│ │ ├── firefox_tables_sql.csv
│ │ └── recovered_testtable.csv
├── sqlitefind.py
└── sqlitetools.py
├── MikeAuty
├── __init__.py
└── scanprof.py
├── MonnappaKa
├── README.md
├── __init__.py
├── ghostrat.py
├── hollowfind.py
├── linux_mem_diff.py
└── psinfo.py
├── NCCGroup
├── README.md
├── __init__.py
└── fwhooks.py
├── NichlasHolm
├── README.md
├── __init__.py
└── carve_packets.py
├── NickGk
├── LICENSE.txt
├── README.md
├── __init__.py
└── facebook_extractor.py
├── PSDispScan
├── __init__.py
└── psdispscan.py
├── PageCheck
├── __init__.py
└── pagecheck.py
├── PeterCasey
├── README.md
├── vis.png
├── visualizer.py
└── vivedump.py
├── PhilipHuppert
├── README.md
├── __init__.py
├── openvpn.py
├── rsakey.py
└── vol-livemigration
│ ├── LICENSE
│ ├── README.md
│ ├── __init__.py
│ ├── extract.py
│ └── vmotion.py
├── ProcessFuzzyHash
├── ProcessFuzzyHash
│ ├── README.md
│ ├── __init__.py
│ ├── _exceptions.py
│ ├── algorithms.py
│ ├── dcfldd.py
│ ├── enumtypes.py
│ ├── installdeps.sh
│ └── processfuzzyhash.py
├── README.md
├── __init__.py
└── processfuzzyhash.pdf
├── README.md
├── RopFind
└── README.md
├── ShachafAtun
└── README.md
├── Shemulator
├── README.md
├── shemulator.py
└── shemulator_api.py
├── ShimcacheMemory
├── README.md
├── __init__.py
└── shimcachemem.py
├── ShuseiTomonaga
└── README.md
├── SlaviParpulev
├── __init__.py
└── psempire.py
├── StanislasLejay
├── README.md
├── __init__.py
├── linux
│ ├── __init__.py
│ └── get_profile.py
└── profilescan.py
├── TakahiroHaruyama
├── IOCs
│ ├── generic
│ │ ├── 10d8f887-b625-426f-b134-8147a780c369_UAC_sdb.ioc
│ │ ├── 26f643d6-6af9-4691-bfc3-f1823d4e9047_code_injection_hook.ioc
│ │ ├── 2823537b-8c9a-454a-8bf4-3aa5ef76ec54_information-stealing_malware.ioc
│ │ ├── 2b5527f3-e5c4-4f0b-b9fc-bcd2221c313c_PIC_PEB.ioc
│ │ ├── 4219a887-d10f-499f-a028-5c459b9c83d5_code_injection_API.ioc
│ │ ├── 710ec573-0b07-40a0-94b6-912af3272b08_LateralMovement_process.ioc
│ │ ├── 7382c170-7e66-4d72-808e-5f703f39a38d_unusual_path.ioc
│ │ ├── 7cf5ca41-5e20-4ff0-8fa4-23510b04485a_PIC.ioc
│ │ ├── 840ae4e7-41eb-4132-a5fe-48c910d99b96_ntfsEA_driver.ioc
│ │ ├── a50223b5-b213-43e9-beac-dfe9c1ca240c_rogue_svchost.ioc
│ │ ├── b28d0314-ca44-45da-97e6-be540a92d929_hollowing.ioc
│ │ ├── b61f88d5-9453-469b-94cd-c5ef59c972db_ntfsEA_proc.ioc
│ │ ├── b78501b8-9aca-4eda-857f-cc409e269259_LateralMovement_file_reg.ioc
│ │ ├── c02075e0-c6a4-4f4b-9ad1-0a8ca9232db3_inline_api_hooks_uknown.ioc
│ │ ├── c7121f8f-8401-4f92-bb02-2be6bb48c3b4_code_injection_pattern.ioc
│ │ ├── cdcd5fdb-fcd3-4947-8c76-d2fbdc1b5f82_UAC_COM.ioc
│ │ ├── e2bd07db-dbfd-45f8-a81d-24314516d0c6_equation_driver_generic.ioc
│ │ ├── e5f73cf8-55ed-463f-81ec-70ffaf81ade9_lsass_checks.ioc
│ │ └── e747cd9d-2ed5-41fe-9e6a-64b49680eeca_unusual_path_shimcache.ioc
│ └── specific
│ │ ├── ec7eed9a-d266-4443-9333-0234cca0f682_equation_proc.ioc
│ │ └── fb4064f7-8fcd-4a81-9584-cd874c365d12_equation_driver.ioc
├── PyIOCe_templates
│ ├── indicator_terms.volatility
│ └── parameters.volatility
├── README.md
├── __init__.py
└── openioc_scan.py
├── TeamDecepticon
└── [VAC] 2018_REPORT_DECEPTICON.pdf
├── TeamMalGround
└── 2018 Volatility Analysis Contest Report_MalGround.pdf
├── Team_HSLFL
└── [VAC2019] Report - Team HSLFS.pdf
├── ThomasChopitea
├── README.md
├── __init__.py
└── autoruns.py
├── ThomasWhite
├── README.md
├── __init__.py
├── bitlocker.py
└── filevault2.py
├── TomSpencer
├── README.md
├── __init__.py
└── usnparser.py
├── TranVienHa
├── README.md
├── __init__.py
├── osint.conf
├── osint.py
└── whitelist.txt
├── WMDF
├── README.md
└── WMDF.pdf
├── WindowsToastNotifications
├── 20190927_Toast Notifications_Writeup.pdf
├── README.md
└── toastplugin.py
├── WyattRoersma
├── README.md
├── __init__.py
└── hpv.py
├── YingLi
├── README.md
├── __init__.py
├── python_strings.py
└── ssh_agent_key.py
├── ZeusScan
├── __init__.py
└── zeusscan.py
├── __init__.py
├── aim4r
├── LICENSE.txt
├── README.md
├── VolDiff.py
└── __init__.py
└── itayk
├── __init__.py
├── antianalysis.py
└── apifinder.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 |
5 | .DS_Store
6 |
7 | # C extensions
8 | *.so
9 |
10 | # Distribution / packaging
11 | .Python
12 | env/
13 | bin/
14 | build/
15 | develop-eggs/
16 | dist/
17 | eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 |
27 | # Installer logs
28 | pip-log.txt
29 | pip-delete-this-directory.txt
30 |
31 | # Unit test / coverage reports
32 | htmlcov/
33 | .tox/
34 | .coverage
35 | .cache
36 | nosetests.xml
37 | coverage.xml
38 |
39 | # Translations
40 | *.mo
41 |
42 | # Mr Developer
43 | .mr.developer.cfg
44 | .project
45 | .pydevproject
46 |
47 | # Rope
48 | .ropeproject
49 |
50 | # Django stuff:
51 | *.log
52 | *.pot
53 |
54 | # Sphinx documentation
55 | docs/_build/
56 |
57 |
--------------------------------------------------------------------------------
/AFF4/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/AFF4/__init__.py
--------------------------------------------------------------------------------
/AFF4/aff4.py:
--------------------------------------------------------------------------------
1 | # Volatility
2 | # AFF4 Standard v1 memory image reader
3 | # Based on WindowsCrashDumpSpace32
4 | #
5 | # Copyright (C) 2017 Schatz Forensic
6 | #
7 | # Authors:
8 | # bradley@schatzforensic.com (Bradley Schatz)
9 | #
10 | # This file is part of Volatility.
11 | #
12 | # Volatility is free software; you can redistribute it and/or modify
13 | # it under the terms of the GNU General Public License as published by
14 | # the Free Software Foundation; either version 2 of the License, or
15 | # (at your option) any later version.
16 | #
17 | # Volatility is distributed in the hope that it will be useful,
18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | # GNU General Public License for more details.
21 | #
22 | # You should have received a copy of the GNU General Public License
23 | # along with Volatility. If not, see .
24 | #
25 |
26 | """ An AS for processing crash dumps """
27 | import struct
28 | import volatility.obj as obj
29 | import volatility.addrspace as addrspace
30 | import volatility.plugins.addrspaces.standard as standard
31 | import logging
32 | import pyaff4
33 | from pyaff4 import data_store
34 | from pyaff4 import lexicon
35 | from pyaff4.container import Container
36 |
37 | LOGGER = logging.getLogger("pyaff4")
38 | LOGGER.setLevel(logging.ERROR)
39 |
40 | # pylint: disable-msg=C0111
41 |
42 | zipFileHeaderMAGIC = "\x50\x4b\x03\x04"
43 |
44 |
45 | class AFF4AddressSpace(standard.FileAddressSpace):
46 | """ This AS supports AFF4 Containers """
47 | order = 31
48 |
49 | def __init__(self, base, config, **kwargs):
50 | standard.FileAddressSpace.__init__(self, base, config, layered=True)
51 |
52 | # Must be stacked on a Raw file based image
53 | self.as_assert(base, "No base address space provided")
54 |
55 | # Must start with the a Zip File Header
56 | self.as_assert((base.read(0, 4) == zipFileHeaderMAGIC), "Header signature invalid")
57 |
58 | # Cant stack an AFF4 image on another AFF4 images
59 | self.as_assert(type(base) != AFF4AddressSpace, "Cant stack AFF4 addressspace on same")
60 | self.fhandle = Container.open(self.name)
61 | self.fsize = self.fhandle.Size()
62 | self.fhandle.seek(0)
63 | dtb = self.fhandle.parent.getDTB()
64 | if dtb != 0:
65 | self.dtb = dtb
66 |
67 | def write(self, _addr, _buf):
68 | if not self._config.WRITE:
69 | return False
70 | raise NotImplementedError("Write support is not implemented for AFF4 containers")
71 |
72 | def get_header(self):
73 | return self.header
74 |
75 | def fread(self, length):
76 | length = int(length)
77 | return self.fhandle.read(length)
78 |
79 | def read(self, addr, length):
80 | addr, length = int(addr), int(length)
81 | try:
82 | self.fhandle.seek(addr)
83 | except (IOError, OverflowError):
84 | return None
85 | data = self.fhandle.read(length)
86 | if len(data) == 0:
87 | return None
88 | return data
89 |
90 | def zread(self, addr, length):
91 | data = self.read(addr, length)
92 | if data is None:
93 | data = "\x00" * length
94 | elif len(data) != length:
95 | data += "\x00" * (length - len(data))
96 |
97 | return data
98 |
99 | def read_long(self, addr):
100 | string = self.read(addr, 4)
101 | longval, = self._long_struct.unpack(string)
102 | return longval
103 |
104 | def get_available_addresses(self):
105 | """ This returns the ranges of valid addresses """
106 | lastOffset = -1
107 | lastLength = -1
108 | for run in self.fhandle.GetRanges():
109 | offset = run.map_offset
110 | length = run.length
111 | if lastOffset == -1:
112 | lastOffset = offset
113 | lastLength = length
114 | else:
115 | if lastOffset + lastLength == offset:
116 | # merge the two
117 | lastLength = lastLength + length
118 | continue
119 | else:
120 | # emit the last
121 | res = (lastOffset, lastLength)
122 | lastOffset = offset
123 | lastLength = length
124 | yield res
125 | yield (lastOffset, lastLength)
126 |
127 | def is_valid_address(self, addr):
128 | if addr == None:
129 | return False
130 | return self.fhandle.tree.overlaps(addr)
131 |
132 | def close(self):
133 | self.fhandle.close()
--------------------------------------------------------------------------------
/AdamBridge/README.md:
--------------------------------------------------------------------------------
1 | Author: Adam Bridge
2 |
3 | See https://github.com/bridgeythegeek for updates and license information.
--------------------------------------------------------------------------------
/AdamBridge/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/AleksanderOsterud/Capabilities-example.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/AleksanderOsterud/Capabilities-example.pdf
--------------------------------------------------------------------------------
/AleksanderOsterud/MemoryDecompression.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/AleksanderOsterud/MemoryDecompression.zip
--------------------------------------------------------------------------------
/AleksanderOsterud/MemoryDecompressionV09 User Guide.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/AleksanderOsterud/MemoryDecompressionV09 User Guide.pdf
--------------------------------------------------------------------------------
/AlessandroDeVito/README.md:
--------------------------------------------------------------------------------
1 | Author: Alessandro DeVito
2 |
3 | See https://github.com/cube0x8 for updates and license information.
--------------------------------------------------------------------------------
/AlessandroDeVito/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/AlizHammond/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | This plugin is intended to detect 'gargoyle' attacks, in which a system timer is used to ROP into VirtualProtect and mark attack code as executable immediately before it executes, and also to mark code as non-executable immediately after its execution.
4 |
5 | The plugin operates by enumerating system timers using the existing 'Timer' plugin, finding those with user-mode APC handers. These handlers are then emulated, via the Unicorn engine, and various suspicious behaviors are reported if present.
6 |
7 | # Installation
8 |
9 | Any environment with Python should work. Known-good environments are Ubuntu Bionic and Win10.
10 |
11 | You'll need to install a couple dependencies. The definitive list of dependencies is the associated test's Dockerfile, which is currently:
12 | ```
13 | apt-get install -y volatility python-pip
14 | python -m pip install scp pysphere unicorn
15 | ```
16 | Also, install distorm3. I suggest using [https://pypi.org/project/distorm3/#files](precompiled binaries).
17 |
18 | Finally, you must install a fixed-up version of the volatility 'timers' plugin, or risk incorrect results. Copy 'timers.py.updated' over your 'volatility\plugins\malware\timers.py' and you should be good to go.
19 |
20 | # Example
21 |
22 | Here's an example, taken from a 64-bit Windows 10 box (the dump is in git LFS so you can follow along):
23 |
24 | ```
25 | $ volatility --plugins=volatility-plugins --profile Win10x64_15063 -f machine-dumps/dormant.vmem gargoyle
26 | Volatility Foundation Volatility Framework 2.6
27 | Process Handler Prolog Adjusted page permissions Branched to code after altering page permission Probable payload
28 | Gargoyle.exe 0x6f0bf3ee POP RCX; POP RSP; RET; MOV EDI, EDI; PUSH RBP True True 0x810000
29 | ```
30 |
31 | Here, the system has found a single timer which has a user-mode payload. It has identified the owning process - Gargoyle.exe, which is the gargoyle PoC - and provided us with a pointer to the handler for any further analysis. It has shown us the first five instructions in the handler, which might immediately raises suspicion, as they appear to be a stack pivot.
32 | The plugin has then emulated the environment, and determined that the handler has called VirtualProtectEx (as reported by 'Adjusted page permissions'). Then, the code branched to the newly-altered page ('Branched to code after altering page permission'). Finally, the address in memory of the ROP payload is provided - 0x810000 in this case.
33 |
34 | Manual analysis to confirm the threat may then be performed.
35 |
36 | # Options
37 |
38 | The plugin, by default, will ignore any timers which are not associated with a valid process context (ie, those where APC->Thread points to no registered system process). This is because the timer list sometimes contains data we cannot make sense of, likely due to undocumented kernel behavior. To disable this, pass the option "ALLTIMERS".
39 |
40 | If you'd like to see what's going on in more detail, specify --VERBOSE. You'll see each Timer being checked, and some details about the emulation process, including a brief instruction trace.
41 |
42 | # Limitations / TODO
43 |
44 | I'm aware of the following limitations:
45 |
46 | * Since we observe only APCs associated with system timers, an attacker may be able to use a different method to queue an APC and remain undetected. It is unclear if this is practical.
47 | * Because we use Capstone to detect the ROP chain which gargoyle uses, we are subject to its limitations. For example, it is unable to deal with memory paging, which causes emulation to finish prematurely under certain circumstances (such as the timer code accessing the PEB via the FS selector).
48 | * Currently, we check only for calls to VirtualProtect and VirtualProtectEx. Malware may hide by sidestepping this and calling NtProtectVirtualMemory directly; it would be good if we can detect emulated kernel-mode transitions via Unicorn, and just detect it at the user-to-kernel transistion.
49 | * We don't check for pure 64-bit attacks. It's not yet clear if these are possible given the x64 calling convention.
50 |
--------------------------------------------------------------------------------
/AndreasSchuster/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/AndreasSchuster/__init__.py
--------------------------------------------------------------------------------
/AndrewCook/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/AndrewCook/__init__.py
--------------------------------------------------------------------------------
/AngeloMirabella/README.md:
--------------------------------------------------------------------------------
1 | Author: Angelo Mirabella
2 |
3 | See https://github.com/Angelomirabella/linux_coredump for updates and license information.
--------------------------------------------------------------------------------
/BlaineStancill/README.md:
--------------------------------------------------------------------------------
1 | Author: BlaineStancill
2 |
3 | See https://github.com/fireeye/win10_volatility for updates and license information.
--------------------------------------------------------------------------------
/CemGurkok/README.md:
--------------------------------------------------------------------------------
1 | Author: Cem Gurkok
2 |
3 | See https://github.com/siliconblade for updates and license information.
--------------------------------------------------------------------------------
/CemGurkok/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/CemGurkok/bitcoin.py:
--------------------------------------------------------------------------------
1 | # Volatility
2 | # Copyright (C) 2007-2013 Volatility Foundation
3 | #
4 | # This file is part of Volatility.
5 | #
6 | # Volatility is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License Version 2 as
8 | # published by the Free Software Foundation. You may not use, modify or
9 | # distribute this program under any other version of the GNU General
10 | # Public License.
11 | #
12 | # Volatility is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with Volatility. If not, see .
19 | #
20 |
21 | """
22 | @author: Cem Gurkok
23 | @license: GNU General Public License 2.0
24 | @contact: cemgurkok@gmail.com
25 | @organization:
26 | """
27 |
28 | import re
29 | import volatility.obj as obj
30 | import volatility.plugins.mac.common as common
31 | import volatility.plugins.mac.pstasks as pstasks
32 | import volatility.debug as debug
33 | import volatility.utils as utils
34 | import volatility.plugins.mac.mac_yarascan as mac_yarascan
35 |
36 | try:
37 | import pycoin.key as pykey
38 | import pycoin.encoding as pyenc
39 | except ImportError:
40 | print "You need to install pycoin for this plugin to run [pip install pycoin]"
41 |
42 | try:
43 | import yara
44 | except ImportError:
45 | print "You need to install yara for this plugin to run [https://github.com/plusvic/yara]"
46 |
47 |
48 | class mac_bitcoin(common.AbstractMacCommand):
49 | """Get bitcoin artifacts from OS X multibit client memory"""
50 |
51 | def __init__(self, config, *args, **kwargs):
52 | common.AbstractMacCommand.__init__(self, config, *args, **kwargs)
53 |
54 | def calculate(self):
55 | # find multibit process
56 | all_tasks = pstasks.mac_tasks(self._config).allprocs()
57 | try:
58 | name_re = re.compile("JavaApplicationS", re.I)
59 | except re.error:
60 | debug.error("Invalid name {0}".format(self._config.NAME))
61 |
62 | bit_tasks = [t for t in all_tasks if name_re.search(str(t.p_comm))]
63 |
64 | # scan for bitcoin addresses with yara, 34 chars, https://en.bitcoin.it/wiki/Address
65 | # Most Bitcoin addresses are 34 characters. They consist of random digits and uppercase
66 | # and lowercase letters, with the exception that the uppercase letter "O", uppercase
67 | # letter "I", lowercase letter "l", and the number "0" are never used to prevent visual ambiguity.
68 | bit_addrs = []
69 | addr_rule = yara.compile(sources = {'n' : 'rule r1 {strings: $a = /[1-9a-zA-z]{34}(?!OIl)/ condition: $a}'})
70 | for task in bit_tasks:
71 | scanner = mac_yarascan.MapYaraScanner(task = task, rules = addr_rule)
72 | for hit, address in scanner.scan():
73 | content = scanner.address_space.zread(address, 34)
74 | if pyenc.is_valid_bitcoin_address(content) and content not in bit_addrs:
75 | bit_addrs.append(content)
76 |
77 | # scan for bitcoin keys with yara, 52 char compressed base58, starts with L or K, https://en.bitcoin.it/wiki/Private_key
78 | addr_key = {}
79 | key_rule = yara.compile(sources = {'n' : 'rule r1 {strings: $a = /(L|K)[0-9A-Za-z]{51}/ condition: $a}'})
80 | for task in bit_tasks:
81 | scanner = mac_yarascan.MapYaraScanner(task = task, rules = key_rule)
82 | for hit, address in scanner.scan():
83 | content = scanner.address_space.zread(address, 52)
84 | if pyenc.is_valid_wif(content):
85 | secret_exp = pyenc.wif_to_secret_exponent(content)
86 | key = pykey.Key(secret_exponent = secret_exp,is_compressed=True)
87 | if key.address() not in addr_key.keys():
88 | addr_key[key.address()] = content
89 | yield(content, key.address())
90 |
91 | # addresses with no known keys
92 | for bit_addr in bit_addrs:
93 | if bit_addr not in addr_key.keys():
94 | yield ("UNKNOWN", bit_addr)
95 |
96 | def render_text(self, outfd, data):
97 | self.table_header(outfd, [("Bitcoin Key (Base58, compressed pub key)", "<52"),("Bitcoin Address","<34")])
98 | for key, address in data:
99 | self.table_row(outfd, key, address)
100 |
--------------------------------------------------------------------------------
/CesarePizzi/README.md:
--------------------------------------------------------------------------------
1 | Author: Cesare Pizzi
--------------------------------------------------------------------------------
/CesarePizzi/Volatility_Plugin_Powershell.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/CesarePizzi/Volatility_Plugin_Powershell.pdf
--------------------------------------------------------------------------------
/Citronneur/README.md:
--------------------------------------------------------------------------------
1 | # volatility-wnf
2 |
3 | See https://github.com/citronneur/volatility-wnf/ for update.
4 |
5 | Browse and dump Windows Notification Facilities
6 |
7 | This plugin is based on work of Alex Ionescu and Gabrielle Viala.
8 |
9 | [https://blog.quarkslab.com/playing-with-the-windows-notification-facility-wnf.html]
10 | [https://www.blackhat.com/us-18/briefings/schedule/#the-windows-notification-facility-peeling-the-onion-of-the-most-undocumented-kernel-attack-surface-yet-11626]
11 | [https://www.youtube.com/watch?v=MybmgE95weo]
12 |
13 | This plugin just walk through all process, or by filter one, and dump all subscribers.
14 | Additionnaly, it can dump associated data from a subscriber.
15 |
16 | ## Install
17 |
18 | Please put *wnf.py* in your volatility plugin folder.
19 |
20 | ## Use
21 |
22 | To dump all subscribers of all process
23 | ```
24 | python vol.py -f your_dump --profile=your_profile wnf
25 | ```
26 |
27 | To dump all subscriber of a particular process
28 | ```
29 | python vol.py -f your_dump --profile=your_profile wnf --pid PID
30 | ```
31 |
32 | To dump data associated to a particular subscriber
33 | ```
34 | python vol.py -f your_dump --profile=your_profile wnfdata -s ADRESS_OF_SUBSCRIBER
35 | ```
36 |
37 | ADRESS_OF_SUBSCRIBER is the first field dump from wnf command.
--------------------------------------------------------------------------------
/CsabaBarta/README.md:
--------------------------------------------------------------------------------
1 | Author: Csaba Barta
2 |
3 | See https://github.com/csababarta for updates and license information.
--------------------------------------------------------------------------------
/CsabaBarta/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/DatQuoc/Readme.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/DatQuoc/Readme.pdf
--------------------------------------------------------------------------------
/DatQuoc/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/DatQuoc/__init__.py
--------------------------------------------------------------------------------
/DaveLasalle/README.md:
--------------------------------------------------------------------------------
1 | Author: Dave Lasalle
2 |
3 | See https://github.com/superponible for updates and license information.
--------------------------------------------------------------------------------
/DaveLasalle/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/DavidQuesada/README.md:
--------------------------------------------------------------------------------
1 | # Splunk_Dash_vol
2 |
3 | You have to use the output csv of volatility to push
4 | your data in splunk quickly.
5 |
6 | After this you just have to copy and paste in an empty
7 | dashboard of Splunk to have this dashboard.
8 |
9 | I will work on it the goal is to have an memory forensic dashboard
10 | which works with volatility.
11 |
--------------------------------------------------------------------------------
/DimaPshoul/DimaPshoul - Volatility Contest 2016 Submission.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/DimaPshoul/DimaPshoul - Volatility Contest 2016 Submission.pdf
--------------------------------------------------------------------------------
/DimaPshoul/README.md:
--------------------------------------------------------------------------------
1 | Author: Dima Pshoul
2 |
3 | See https://github.com/papadp for updates and license information.
--------------------------------------------------------------------------------
/DimaPshoul/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/DimaPshoul/malfofind.py:
--------------------------------------------------------------------------------
1 | import os
2 | import volatility.utils as utils
3 | import volatility.obj as obj
4 | import volatility.debug as debug
5 | import volatility.win32.tasks as tasks
6 | import volatility.win32.modules as modulesf
7 | import volatility.plugins.taskmods as taskmods
8 | import volatility.plugins.vadinfo as vadinfo
9 | import volatility.plugins.overlays.windows.windows as windows
10 | import volatility.constants as constants
11 | import volatility.plugins.malware.malfind as malfind
12 |
13 |
14 |
15 |
16 | class Malfofind(vadinfo.VADDump):
17 | "Find indications of process hollowing/RunPE injections"
18 |
19 | def __init__(self, config, *args, **kwargs):
20 | vadinfo.VADDump.__init__(self, config, *args, **kwargs)
21 | config.remove_option("BASE")
22 | config.remove_option("PID")
23 | config.remove_option("NAME")
24 |
25 | def generate_output(self, outfd, vad, task, file_object_name, peb_image_path_name):
26 | # this function will output data for a given VAD passed to it
27 |
28 | content = None
29 |
30 | outfd.write("Process: {0} Pid: {1} Ppid: {2}\n".format(
31 | task.ImageFileName, task.UniqueProcessId, task.InheritedFromUniqueProcessId))
32 |
33 | outfd.write("Address: {0:#x} Protection: {1}\n".format(
34 | vad.Start, vadinfo.PROTECT_FLAGS.get(vad.VadFlags.Protection.v(), "")))
35 |
36 | if peb_image_path_name != None:
37 | outfd.write("Initially mapped file object: {0}\n".format(peb_image_path_name))
38 | else:
39 | outfd.write("Initially mapped file object: {0}\n".format("None"))
40 |
41 | if file_object_name != None:
42 | outfd.write("Currently mapped file object: {0}\n".format(file_object_name))
43 | else:
44 | outfd.write("Currently mapped file object: {0}\n".format("None"))
45 |
46 |
47 | address_space = task.get_process_address_space()
48 | content = address_space.zread(vad.Start, 64)
49 |
50 | if content:
51 | outfd.write("{0}\n".format("\n".join(
52 | ["{0:#010x} {1:<48} {2}".format(vad.Start + o, h, ''.join(c))
53 | for o, h, c in utils.Hexdump(content)
54 | ])))
55 |
56 | outfd.write("\n")
57 | outfd.write("\n".join(
58 | ["{0:#010x} {1:<16} {2}".format(o, h, i)
59 | for o, i, h in malfind.Disassemble(content, vad.Start)
60 | ]))
61 |
62 | outfd.write("\n\n")
63 |
64 | # dump vad incase -D was specified
65 | if self._config.DUMP_DIR:
66 | filename = os.path.join(self._config.DUMP_DIR,
67 | "process.{0:#x}.{1:#x}.dmp".format(
68 | task.obj_offset, vad.Start))
69 | self.dump_vad(filename, vad, address_space)
70 |
71 | def render_text(self, outfd, data):
72 |
73 | # check if supplied path is a directory
74 | if self._config.DUMP_DIR and not os.path.isdir(self._config.DUMP_DIR):
75 | debug.error(self._config.DUMP_DIR + " is not a directory")
76 |
77 | for task in data:
78 | peb_image_path_name = None
79 | peb_image_base = None
80 |
81 | # check if peb is available
82 | if task.Peb != None:
83 | if task.Peb.ProcessParameters != None and task.Peb.ProcessParameters.ImagePathName:
84 | #grab image base and image path name from peb
85 | peb_image_path_name = str(task.Peb.ProcessParameters.ImagePathName)
86 | peb_image_base = task.Peb.ImageBaseAddress
87 |
88 | # iterate over vads, for each vad check if there is a mapped file object,
89 | # check if PEB LDR module objects are mapped with the same name and same
90 | # base address as the the VAD specifies, if not we consider it and indictaion
91 | # of process hollowing and send the vads details to self.generate_output()
92 |
93 | for vad in task.VadRoot.traverse():
94 | file_object_name = None
95 | file_object = None
96 | if vad != None:
97 | try:
98 | control_area = vad.ControlArea
99 | if vad.VadFlags.PrivateMemory != 1 and control_area:
100 | if control_area:
101 | file_object = vad.FileObject
102 | if file_object != None and file_object.FileName:
103 | file_object_name = str(file_object.FileName)
104 | except AttributeError:
105 | pass
106 | if peb_image_base != None:
107 | if vad.Start == peb_image_base:
108 | if peb_image_path_name != None:
109 | if file_object_name == None:
110 | self.generate_output(outfd, vad, task, file_object_name, peb_image_path_name)
111 |
112 | else:
113 | peb_image_path_name = peb_image_path_name.lower()
114 | if peb_image_path_name.startswith(r"\systemroot"):
115 | peb_image_path_name = peb_image_path_name.replace("\\systemroot", "\\windows")
116 | if peb_image_path_name.find(file_object_name.lower()) == -1 or peb_image_path_name.find(str(task.ImageFileName).lower()) == -1:
117 | self.generate_output(outfd, vad, task, file_object_name, peb_image_path_name)
118 | else:
119 | continue
120 |
121 |
--------------------------------------------------------------------------------
/ESET_Browserhooks/README.md:
--------------------------------------------------------------------------------
1 | Author: Peter Kálnai and Michal Poslušný
2 |
3 | See https://github.com/eset/volatility-browserhooks for updates and license information.
--------------------------------------------------------------------------------
/ESET_Browserhooks/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ESET_Browserhooks/browserhooks_documentation.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/ESET_Browserhooks/browserhooks_documentation.pdf
--------------------------------------------------------------------------------
/EWF/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/EWF/__init__.py
--------------------------------------------------------------------------------
/EWF/ewf.py:
--------------------------------------------------------------------------------
1 | """ This Address Space allows us to open ewf files """
2 |
3 | #pylint: disable-msg=C0111
4 |
5 | from ctypes import CDLL, c_char_p, c_int, pointer, c_ulonglong, c_ulong, create_string_buffer
6 | import ctypes.util
7 | import volatility.plugins.addrspaces.standard as standard
8 |
9 | possible_names = ['libewf-1', 'ewf', ]
10 | for name in possible_names:
11 | resolved = ctypes.util.find_library(name)
12 | if resolved:
13 | break
14 |
15 | if resolved:
16 | libewf = CDLL(resolved)
17 |
18 | if not resolved or not libewf._name:
19 | libewf = None
20 |
21 | class ewffile(object):
22 | """ A file like object to provide access to the ewf file """
23 | def __init__(self, volumes):
24 | if isinstance(volumes, str):
25 | volumes = [volumes, ]
26 |
27 | volume_array = c_char_p * len(volumes)
28 | self.handle = libewf.libewf_open(volume_array(*volumes), c_int(len(volumes)),
29 | c_int(1))
30 | if self.handle == 0:
31 | raise RuntimeError("Unable to open ewf file")
32 |
33 | self.readptr = 0
34 | size_p = pointer(c_ulonglong(0))
35 | libewf.libewf_get_media_size(self.handle, size_p)
36 | self.size = size_p.contents.value
37 |
38 | def seek(self, offset, whence = 0):
39 | if whence == 0:
40 | self.readptr = offset
41 | elif whence == 1:
42 | self.readptr += offset
43 | elif whence == 2:
44 | self.readptr = self.size + offset
45 |
46 | self.readptr = min(self.readptr, self.size)
47 |
48 | def tell(self):
49 | return self.readptr
50 |
51 | def read(self, length):
52 | buf = create_string_buffer(length)
53 | length = libewf.libewf_read_random(self.handle, buf,
54 | c_ulong(length),
55 | c_ulonglong(self.readptr))
56 |
57 | return buf.raw[:length]
58 |
59 | def close(self):
60 | libewf.libewf_close(self.handle)
61 |
62 | def get_headers(self):
63 | properties = ["case_number", "description", "examinier_name",
64 | "evidence_number", "notes", "acquiry_date",
65 | "system_date", "acquiry_operating_system",
66 | "acquiry_software_version", "password",
67 | "compression_type", "model", "serial_number", ]
68 |
69 | ## Make sure we parsed all headers
70 | libewf.libewf_parse_header_values(self.handle, c_int(4))
71 | result = {'size': self.size}
72 | buf = create_string_buffer(1024)
73 | for p in properties:
74 | libewf.libewf_get_header_value(self.handle, p, buf, 1024)
75 | result[p] = buf.value
76 |
77 | ## Get the hash
78 | if libewf.libewf_get_md5_hash(self.handle, buf, 16) == 1:
79 | result['md5'] = buf.raw[:16]
80 |
81 | return result
82 |
83 | def ewf_open(volumes):
84 | return ewffile(volumes)
85 |
86 | class EWFAddressSpace(standard.FileAddressSpace):
87 | """ An EWF capable address space.
88 |
89 | In order for us to work we need:
90 | 1) There must be a base AS.
91 | 2) The first 6 bytes must be 45 56 46 09 0D 0A (EVF header)
92 | """
93 | order = 20
94 | def __init__(self, base, config, **kwargs):
95 | self.as_assert(libewf, "No libEWF implementation found")
96 | standard.FileAddressSpace.__init__(self, base, config, layered = True)
97 | self.as_assert(base, "No base address space provided")
98 | self.as_assert(base.read(0, 6) == "\x45\x56\x46\x09\x0D\x0A", "EWF signature not present")
99 | self.fhandle = ewf_open([self.name])
100 | self.fhandle.seek(0, 2)
101 | self.fsize = self.fhandle.tell()
102 | self.fhandle.seek(0)
103 |
104 | def write(self, _addr, _buf):
105 | if not self._config.WRITE:
106 | return False
107 | raise NotImplementedError("Write support is not yet implemented for EWF files")
108 |
--------------------------------------------------------------------------------
/ElmarNabigaev/README.md:
--------------------------------------------------------------------------------
1 | Author: Elmar Nabigaev
--------------------------------------------------------------------------------
/EnumFunc/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/EnumFunc/__init__.py
--------------------------------------------------------------------------------
/EnumFunc/enumfunc.py:
--------------------------------------------------------------------------------
1 | # Volatility
2 | # Copyright (c) 2012 Michael Ligh (michael.ligh@mnin.org)
3 | #
4 | # This file is part of Volatility.
5 | #
6 | # Volatility is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 2 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # Volatility is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with Volatility. If not, see .
18 | #
19 |
20 | import volatility.plugins.taskmods as taskmods
21 | import volatility.utils as utils
22 | import volatility.win32.tasks as tasks
23 | import volatility.win32.modules as modules
24 | import volatility.plugins.filescan as filescan
25 | import volatility.plugins.modscan as modscan
26 |
27 | class EnumFunc(taskmods.DllList):
28 | """Enumerate imported/exported functions"""
29 |
30 | def __init__(self, config, *args, **kwargs):
31 | taskmods.DllList.__init__(self, config, *args, **kwargs)
32 | config.remove_option("PID")
33 | config.remove_option("OFFSET")
34 | config.add_option("SCAN", short_option = 's', default = False,
35 | action = 'store_true', help = 'Scan for objects')
36 | config.add_option("PROCESS-ONLY", short_option = 'P', default = False,
37 | action = 'store_true', help = 'Process only')
38 | config.add_option("KERNEL-ONLY", short_option = 'K', default = False,
39 | action = 'store_true', help = 'Kernel only')
40 | config.add_option("IMPORT-ONLY", short_option = 'I', default = False,
41 | action = 'store_true', help = 'Imports only')
42 | config.add_option("EXPORT-ONLY", short_option = 'E', default = False,
43 | action = 'store_true', help = 'Exports only')
44 |
45 | def calculate(self):
46 | addr_space = utils.load_as(self._config)
47 |
48 | tasklist = []
49 | modslist = []
50 |
51 | if self._config.SCAN:
52 | if not self._config.KERNEL_ONLY:
53 | for t in filescan.PSScan(self._config).calculate():
54 | v = self.virtual_process_from_physical_offset(addr_space, t.obj_offset)
55 | if v:
56 | tasklist.append(v)
57 | if not self._config.PROCESS_ONLY:
58 | modslist = [m for m in modscan.ModScan(self._config).calculate()]
59 | else:
60 | if not self._config.KERNEL_ONLY:
61 | tasklist = [t for t in tasks.pslist(addr_space)]
62 | if not self._config.PROCESS_ONLY:
63 | modslist = [m for m in modules.lsmod(addr_space)]
64 |
65 | for task in tasklist:
66 | for mod in task.get_load_modules():
67 | yield task, mod
68 |
69 | for mod in modslist:
70 | yield None, mod
71 |
72 | def render_text(self, outfd, data):
73 |
74 | outfd.write("{0:<20} {1:<10} {2:<20} {3:<10} {4:<20} {5}\n".format(
75 | "Process", "Type", "Module", "Ordinal", "Address", "Name"))
76 |
77 | for process, module in data:
78 | if not self._config.IMPORT_ONLY:
79 | for o, f, n in module.exports():
80 | outfd.write("{0:<20} {1:<10} {2:<20} {3:<10} {4:#018x} {5}\n".format(
81 | process.ImageFileName if process else "",
82 | "Export", module.BaseDllName,
83 | o,
84 | (module.DllBase + f) if f else 0, # None if forwarded
85 | n or '' # None if paged
86 | ))
87 | if not self._config.EXPORT_ONLY:
88 | for dll, o, f, n in module.imports():
89 | outfd.write("{0:<20} {1:<10} {2:<20} {3:<10} {4:#018x} {5}\n".format(
90 | process.ImageFileName if process else "",
91 | "Import", module.BaseDllName,
92 | o,
93 | f or 0, # None if paged
94 | dll + "!" + n or '' # None if paged or imported by ordinal
95 | ))
96 |
--------------------------------------------------------------------------------
/FabienPerigaud/README.md:
--------------------------------------------------------------------------------
1 | Author: Fabien Periguad
2 |
3 | See https://bitbucket.org/cybertools/volatility_plugins/wiki/Home for updates and license information.
--------------------------------------------------------------------------------
/FabienPerigaud/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/FabioPagani/README.md:
--------------------------------------------------------------------------------
1 | ## Introduction
2 |
3 | This Volatity Plugin Contest submission contains two contributions to
4 | the Volatility framework and to the memory forensics fields. The first
5 | contributions contains several new Volatility plugins to list tasks
6 | and kernel modules under Linux. The second one is instead a novel way
7 | to extract the kallsyms from a memory dump in an automated way.
8 |
9 | ## Plugins to list module and kallsyms
10 |
11 | As a side effect of our latest paper - where we constructed and studied a directed graph of kernel structs [1] - we were able to find new ways to list Linux processes and kernel modules.
12 | As you know (even better than me!) being able to reach the same information from different ways is crucial if smearing affects a memory dump or DKOM attacks were performed.
13 | The directory `new_plugins` contains the following novel plugins:
14 |
15 | 1) `cgrp_dfl_pslist` and `css_set_pslist`: they list all the threads in the dump by traversing cgroup related structs
16 | 2) `inode_pslist`: lists every process that has at least one memory mapped file
17 | 3) `workqueues`: lists every kernel workers (which are part of the process list)
18 | 4) `terminated_tasks`: lists terminated tasks by deferencing certain field of task_struct and signal_struct which are not update when a task dies (e.g task_struct.last_wakee)
19 | 5) `mod_tree`: walks a latch tree rooted at the kernel symbol `mod_tree` to list kernel modules
20 |
21 | All of this plugins works with a normal Volatility profile, except `workqueues` that needs few new structs definitions. For this reason, we included in this submission also an updated `module.c` file.
22 |
23 |
24 | ## Kallsyms extraction
25 |
26 | Imagine that you have a memory dump but - for whatever reason - the profile has an invalid or corrupted System.map file!
27 | There have been few attempts in the past to automatically extract this information from a memory dump [2][3].
28 | Unfortunately these approaches assume to know where the kernel is loaded in the virtual and physical address space, thus failing when KASLR is enabled.
29 | Moreover, they are able to extract only the ksymtab - which contains a limited subset of kernel symbols (the ones exported with EXPORT_SYMBOL macro).
30 | With this contributions we show a reliable and automated way to extract the kernel kallsyms - which are stored in kernel memory in a compressed form.
31 |
32 | In a nutshell our approach locates, extracts and executes the function `kallsyms_on_each_symbol` from a memory dump. This function takes care of uncompressing the kallsyms and accepts a function pointer as parameter - which gets called every time a kallsym is uncompressed!
33 |
34 | More specifically, our approach can be divided in the following steps:
35 | 1) First of all we find the physical location of the string "kallsyms_on_each_symbols\x00"
36 | 2) Then we search in the dump for a candidate ksymtab. This table contains several `struct kernel_symbols` which contains two fields: `value` and `name`. The first contains the virtual address of the symbol, while the latter is a pointer to a string representing the name of the symbol. For this reason, finding a candidate symtab is a matter of searching for a sequence (longer than a threshold) of pairs of kernel addresses.
37 | 3) At this point, we use the following insight: KASLR randomize the virtual and physical space at a page granularity. This means that the correct ksymtab should contain at least one `struct kernel_symbol` where the page offset of the name field matches the page offset of the physical location of the string (found at step 1)).
38 | 4) When we find such a `kernel_symbol`, since the kernel is mapped contigously, to find the physical address of the value field we can just do: string physical address + (value virtual address - name virtual address)
39 | 5) At this point we know the virtual address of the kallsyms_on_each_function and its physical address: we are ready to extract the sorrounding of this address, load the in Unicorn and execute the function!
40 |
41 | I tried the script against several versions of the kernel and it worked flawlessy even when on the dumps of The Art Of Memory Forensics :)
42 |
43 | ### Limitations and Future Work:
44 | First of all, this works only if the kernel was compiled with CONFIG_MODULES - otherwise the kallsyms are never created in the first place.
45 |
46 | Moreover, the latest versions of the kernel introduced CONFIG_HAVE_ARCH_PREL32_RELOCATIONS. This makes everything more tricky `struct kernel_symbol` does not contain virtual addresses anymore but only offsets. Therefore, while we can still find the physical address of the function in the dump, we miss its virtual address. I have the strong feeling that by analyzing the code we can still find the correct virtual address (maybe with some small bruteforcing involved?), but I did not have time tothes this.
47 |
48 | Finally, this function can also list the installed modules symbols (it calls `module_kallsyms_on_each_symbol`). The problem here is that the memory where this information resides must be correctly loaded in the emulator (modules area is not contigous to the kernel code, so extracting more memory from the dump is not enough). But from the ksymtab we know where `init_level4_pgt` or `init_top_pgt` are - so we could walk the page tables and set everything up correctly in the emulator!
49 |
50 | ## Conclusion
51 | I really believe that memory forensics on Linux will be "the next big thing" in this field. This submission steps the game up, with new plugins to analyze a memory dump and a robust, fast and generic (kernels up to 10 years ago should be supported) approach to extract the kallsyms. For these reasons, I really belive that this submission deserves to win this year contest ;-)
52 |
53 |
54 | ### References
55 | [1] https://www.usenix.org/system/files/sec19-pagani.pdf
56 | [2] https://github.com/emdel/ksfinder
57 | [3] https://github.com/psviderski/volatility-android/blob/master/volatility/plugins/linux/auto_ksymbol.py
--------------------------------------------------------------------------------
/FabioPagani/volc.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/FabioPagani/volc.zip
--------------------------------------------------------------------------------
/FrancescoPicasso/README.md:
--------------------------------------------------------------------------------
1 | Author: Francesco Picasso
2 |
3 | See https://github.com/dfirfpi/hotoloti for updates and license information.
--------------------------------------------------------------------------------
/FrancescoPicasso/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/FrankBlock/README.md:
--------------------------------------------------------------------------------
1 | Author: Frank Block
2 |
3 | See http://coding.f-block.org for updates and license information.
--------------------------------------------------------------------------------
/FrankBlock/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/FrankBlock/keepassx.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017, Frank Block, ERNW GmbH
2 |
3 | """Gathers information about password entries for keepassx.
4 | The retrieved content of those entries comprises the username, title, URL
5 | and Comment.
6 | """
7 |
8 | import struct
9 | import volatility.plugins.linux.heap_analysis as heap_analysis
10 | import volatility.plugins.linux.common as linux_common
11 | import volatility.plugins.linux.pslist as linux_pslist
12 |
13 |
14 |
15 | class linux_keepassx(heap_analysis.HeapAnalysis):
16 | """Gathers password entries for keepassx.
17 | The retrieved content of those entries comprises the username, title, URL
18 | and Comment."""
19 |
20 | def calculate(self):
21 | linux_common.set_plugin_members(self)
22 | tasks = linux_pslist.linux_pslist(self._config).calculate()
23 |
24 | for task in tasks:
25 | if self.init_for_task(task):
26 |
27 | chunks_dict = dict()
28 |
29 | data_offset = self.profile.get_obj_offset("malloc_chunk", "fd")
30 |
31 | for chunk in self.get_all_allocated_chunks():
32 | chunks_dict[chunk.v() + data_offset] = chunk
33 |
34 | if self.profile.metadata.get('memory_model') == '64bit':
35 | string_offset = 26
36 | relevant_chunk_size = 192
37 | pointer_offsets = [16, 24, 32, 64]
38 |
39 | else:
40 | string_offset = 18
41 | relevant_chunk_size = 96
42 | pointer_offsets = [12, 16, 20, 36]
43 |
44 | entry_number = 1
45 |
46 | for chunk in chunks_dict.values():
47 |
48 | try:
49 | # chunks containing refs to password entries typically
50 | # have a size of 96 in the tested 32 bit environment
51 | if not chunk.chunksize() == relevant_chunk_size:
52 | continue
53 |
54 | p_entry_data = chunk.to_string()
55 |
56 | field_strings = []
57 |
58 | # the pointers to title, username and so on are at
59 | # these offsets
60 | for i in pointer_offsets:
61 | if self.profile.metadata.get('memory_model') == '32bit':
62 | pointer = struct.unpack('I',
63 | p_entry_data[i:i+4])[0]
64 | else:
65 | pointer = struct.unpack('Q',
66 | p_entry_data[i:i+8])[0]
67 |
68 | # if there is no chunk for the given pointer, we
69 | # most probably have a wrong chunk. this will
70 | # throw a KeyError exception and we proceed with
71 | # the next chunk
72 | curr_chunk_data = chunks_dict[pointer].to_string()
73 |
74 | string_size = struct.unpack(
75 | 'I', curr_chunk_data[8:12])[0]
76 |
77 | string_size *= 2
78 |
79 | curr_string = curr_chunk_data[
80 | string_offset:string_offset+string_size]
81 |
82 | curr_string = curr_string.decode('utf-16-le')
83 |
84 | field_strings.append(repr(curr_string))
85 |
86 |
87 | yield (task.pid,
88 | entry_number,
89 | field_strings[0],
90 | field_strings[1],
91 | field_strings[2],
92 | field_strings[3])
93 |
94 | entry_number += 1
95 |
96 | except (KeyError, UnicodeDecodeError):
97 | # a password entry struct not containing a pointer to
98 | # a chunk => out of scope
99 | pass
100 |
101 | def render_text(self, outfd, data):
102 | self.table_header(outfd, [
103 | ("pid", "6"),
104 | ("entry", ""),
105 | ("title", ""),
106 | ("url", ""),
107 | ("username", ""),
108 | ("comment", "")
109 | ])
110 |
111 | for entry in data:
112 | self.table_row(outfd, entry[0],entry[1],entry[2],entry[3],entry[4],entry[5])
113 |
--------------------------------------------------------------------------------
/GlennEdwards/README.md:
--------------------------------------------------------------------------------
1 | Author: Glenn Edwards
2 |
3 | See https://github.com/hiddenillusion for updates and license information.
--------------------------------------------------------------------------------
/GlennEdwards/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/JPCERT/LICENSE.txt:
--------------------------------------------------------------------------------
1 | LICENSE
2 | Copyright (C) 2015 JPCERT Coordination Center. All Rights Reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following acknowledgments and disclaimers.
8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following acknowledgments and disclaimers in the documentation and/or other materials provided with the distribution.
9 | 3. Products derived from this software may not include "JPCERT Coordination Center" in the name of such derived product, nor shall "JPCERT Coordination Center" be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact pr@jpcret.or.jp.
10 |
11 | ACKNOWLEDGMENTS AND DISCLAIMERS
12 | Copyright (C) 2015 JPCERT Coordination Center
13 |
14 | This software is based upon work funded and supported by the Ministry of
15 | Economy, Trade and Industry.
16 |
17 | Any opinions, findings and conclusions or recommendations expressed in this
18 | software are those of the author(s) and do not necessarily reflect the views of
19 | the Ministry of Economy, Trade and Industry.
20 |
21 | NO WARRANTY. THIS JPCERT COORDINATION CENTER SOFTWARE IS FURNISHED ON
22 | AN "AS-IS" BASIS. JPCERT COORDINATION CENTER MAKES NO WARRANTIES OF
23 | ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT
24 | NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY,
25 | EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE SOFTWARE. JPCERT
26 | COORDINATION CENTER DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH
27 | RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
28 |
29 | This software has been approved for public release and unlimited distribution.
30 |
--------------------------------------------------------------------------------
/JPCERT/README.md:
--------------------------------------------------------------------------------
1 | Author: JPCERT/CC
2 |
3 | See https://github.com/JPCERTCC/aa-tools for updates and license information.
--------------------------------------------------------------------------------
/JPCERT/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/JamaalSpeights/README.md:
--------------------------------------------------------------------------------
1 | Author: Jamaal Speights
2 |
3 | (At this time, the author is not known to have a GitHub profile page)
--------------------------------------------------------------------------------
/JamaalSpeights/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/JamesHall_KevinBreen/README.md:
--------------------------------------------------------------------------------
1 | Author: James Hall and Kevin Breen
2 |
3 | See https://github.com/kevthehermit/volatility_plugins/tree/master/usbstor for updates and license information.
--------------------------------------------------------------------------------
/JamesHall_KevinBreen/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/JavierVallejo/README.md:
--------------------------------------------------------------------------------
1 | Author: Javier Vicente Vallejo
2 |
3 | See http://www.vallejo.cc for updates and license information.
--------------------------------------------------------------------------------
/JavierVallejo/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/JeffBryner/README.md:
--------------------------------------------------------------------------------
1 | Author: Jeff Bryner
2 |
3 | See https://github.com/jeffbryner for updates and license information.
--------------------------------------------------------------------------------
/JeffBryner/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/JoeGreenwood/README.md:
--------------------------------------------------------------------------------
1 | Author: Joe Greenwood
2 |
3 | See https://github.com/4ARMED/volatility-attributeht for updates and license information.
--------------------------------------------------------------------------------
/JoeGreenwood/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/KSLGroup_Threadmap/README.md:
--------------------------------------------------------------------------------
1 | Author: Liam Stein, Shachaf Atun and Kyle Ness (KSLGroup)
2 |
3 | See https://github.com/kslgroup/threadmap for updates and license information.
--------------------------------------------------------------------------------
/KSLGroup_Threadmap/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/KSLGroup_Threadmap/threadmap documentation.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/KSLGroup_Threadmap/threadmap documentation.pdf
--------------------------------------------------------------------------------
/KevinBreen/README.md:
--------------------------------------------------------------------------------
1 | Author: Kevin Breen
2 |
3 | See https://github.com/kevthehermit/volatility_plugins/tree/master/lastpass for updates and license information.
--------------------------------------------------------------------------------
/KevinBreen/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/KudelskiSecurity/README.md:
--------------------------------------------------------------------------------
1 | Author: Kudelski Security
2 |
3 | See https://github.com/kudelskisecurity for updates and license information.
--------------------------------------------------------------------------------
/KudelskiSecurity/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/KudelskiSecurity/dyrescan.py:
--------------------------------------------------------------------------------
1 | # Dyre (Dyreza) configuration extractor - v 1.0
2 | # Copyright (c) 2015 Nagravision SA
3 | # Based on plugin by Author: Brian Baskin (Java RAT detection)
4 | #
5 | # This program is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 2 of the License, or (at
8 | # your option) any later version.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program; if not, write to the Free Software
17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | import volatility.plugins.taskmods as taskmods
20 | import volatility.win32.tasks as tasks
21 | import volatility.utils as utils
22 | import volatility.debug as debug
23 | import volatility.plugins.malware.malfind as malfind
24 | import volatility.conf as conf
25 | import string
26 |
27 | try:
28 | import yara
29 | HAS_YARA = True
30 | except ImportError:
31 | HAS_YARA = False
32 |
33 |
34 | YARA_SIGS = {
35 | 'dyre_conf' : 'rule dyre_conf {strings: $a = // condition: $a}'
36 | }
37 |
38 | config = conf.ConfObject()
39 | config.add_option('CONFSIZE', short_option='C', default=190000,
40 | help='Config data size',
41 | action='store', type='int')
42 | config.add_option('YARAOFFSET', short_option='Y', default=0,
43 | help='YARA start offset',
44 | action='store', type='int')
45 |
46 | class DyreScan(taskmods.PSList):
47 | """ Extract Dyre Configuration from processes """
48 |
49 | def get_vad_base(self, task, address):
50 | for vad in task.VadRoot.traverse():
51 | if address >= vad.Start and address < vad.End:
52 | return vad.Start
53 | return None
54 |
55 | def calculate(self): ### Not used here but kept if needed for improvements
56 | """ Required: Runs YARA search to find hits """
57 | if not HAS_YARA:
58 | debug.error('Yara must be installed for this plugin')
59 |
60 | addr_space = utils.load_as(self._config)
61 | rules = yara.compile(sources=YARA_SIGS)
62 | for task in self.filter_tasks(tasks.pslist(addr_space)):
63 | scanner = malfind.VadYaraScanner(task=task, rules=rules)
64 | for hit, address in scanner.scan():
65 | vad_base_addr = self.get_vad_base(task, address)
66 | yield task, address
67 |
68 | def make_printable(self, input): ### Not used here but kept if needed for improvements
69 | """ Optional: Remove non-printable chars from a string """
70 | input = input.replace('\x09', '') # string.printable doesn't remove backspaces
71 | return ''.join(filter(lambda x: x in string.printable, input))
72 |
73 |
74 | def render_text(self, outfd, data):
75 | """ Required: Parse data and display """
76 | config = None
77 | full_list = list()
78 | delim = '-=' * 39 + '-'
79 | rules = yara.compile(sources=YARA_SIGS)
80 | outfd.write('YARA rule: {0}\n'.format(YARA_SIGS))
81 | outfd.write('YARA offset: {0}\n'.format(self._config.YARAOFFSET))
82 | outfd.write('Configuration size: {0}\n'.format(self._config.CONFSIZE))
83 | for task, address in data:
84 | outfd.write('{0}\n'.format(delim))
85 | outfd.write('Configuration found in Process: {0} ({1})\n\n'.format(task.ImageFileName, task.UniqueProcessId))
86 | proc_addr_space = task.get_process_address_space()
87 | conf_data = proc_addr_space.read(address + self._config.YARAOFFSET, self._config.CONFSIZE)
88 | try:
89 | config = conf_data.splitlines()
90 | except:
91 | pass
92 | config_tag = ("", "", "srv_name", "", "", "", "", "", ".reloc", "[nowait]") # remove line not relevant
93 | if config is not None:
94 | for i in config:
95 | if any(s in i for s in config_tag):
96 | pass
97 | else:
98 | full_list.append(i)
99 | url_match = (".i2p", ".com", "/*", "www.", ".aspx", ".do", ".htm", ".jsp", ".cfm", ".co.uk")
100 | if full_list:
101 | for j in sorted(set(full_list)):
102 | if any(t in j for t in url_match):
103 | outfd.write('\t{0}\n'.format(j))
104 | else:
105 | pass
106 |
--------------------------------------------------------------------------------
/LoicJaquemet/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LorenzLiebler/2018_volcon_liebler_pub.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/LorenzLiebler/2018_volcon_liebler_pub.pdf
--------------------------------------------------------------------------------
/MarianoGraziano/README.md:
--------------------------------------------------------------------------------
1 | Author: Mariano Graziano
2 |
3 | See https://github.com/emdel for updates and license information.
--------------------------------------------------------------------------------
/MarianoGraziano/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/MarianoGraziano/kstackps.py:
--------------------------------------------------------------------------------
1 | # Volatility
2 | #
3 | # This program is free software; you can redistribute it and/or modify
4 | # it under the terms of the GNU General Public License as published by
5 | # the Free Software Foundation; either version 2 of the License, or (at
6 | # your option) any later version.
7 | #
8 | # This program is distributed in the hope that it will be useful, but
9 | # WITHOUT ANY WARRANTY; without even the implied warranty of
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 | # General Public License for more details.
12 | #
13 | # You should have received a copy of the GNU General Public License
14 | # along with this program; if not, write to the Free Software
15 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 |
17 | """
18 | @author: Mariano `emdel` Graziano
19 | @license: GNU General Public License 2.0 or later
20 | @contact: graziano@eurecom.fr
21 | @organization: Eurecom
22 | """
23 |
24 | import volatility.utils as utils
25 | import volatility.scan as scan
26 | import volatility.plugins.linux.common as linux_common
27 | import volatility.obj as obj
28 | import struct, collections
29 |
30 |
31 | '''
32 | References:
33 | - A guide to kernel exploitation - pages 126-132
34 | - https://jon.oberheide.org/blog/2010/11/29/exploiting-stack-overflows-in-the-linux-kernel/
35 | - Robust Signatures for Kernel Data Structures - http://www.cc.gatech.edu/~brendan/ccs09_siggen.pdf
36 | - Linux kernel source code
37 | '''
38 |
39 |
40 | SIZE_x32 = 0x04
41 | KERNEL_BASE_x32 = 0xc0000000
42 | KERNEL_MAX_x32 = 0xffffffff
43 |
44 |
45 | class kstackps(linux_common.AbstractLinuxCommand):
46 | '''
47 | Walk the kernel pages to discover 'task_struct' data structures.
48 | We are interested in kernel stack pages and we leverage the
49 | thread_info data structure, the first field is a pointer to the
50 | task_struct owning the current kernel stack (see the references)
51 | This is just a POC.
52 | TODO:
53 | * x64 support
54 | * Android support
55 | * stronger signature for the task_struct [DONE]
56 | * Find a way to distinguish between dead and hidden
57 | processes - Exit_state?
58 | * psscan like plugin (see the previous point)
59 | * Create a real Scanner
60 | '''
61 | def __init__(self, config, *args, **kwargs):
62 | linux_common.AbstractLinuxCommand.__init__(self, config, *args, **kwargs)
63 |
64 | def calculate(self):
65 | linux_common.set_plugin_members(self)
66 | for offset in xrange(KERNEL_BASE_x32, KERNEL_MAX_x32, 0x2000):
67 | try: thread_info_addr = struct.unpack(' KERNEL_MAX_x32: continue
70 | cur = obj.Object("task_struct", thread_info_addr, self.addr_space)
71 | # TODO: improve task_struct validation -- See moyix approach
72 | if cur.se.v() > KERNEL_BASE_x32 and cur.se.v() < KERNEL_MAX_x32 and \
73 | cur.sched_info.v() > KERNEL_BASE_x32 and cur.sched_info.v() < KERNEL_MAX_x32 and \
74 | cur.stack > KERNEL_BASE_x32 and cur.stack < KERNEL_MAX_x32 and \
75 | cur.cred.v() > KERNEL_BASE_x32 and cur.cred.v() < KERNEL_MAX_x32 and \
76 | cur.thread.v() > KERNEL_BASE_x32 and cur.thread.v() < KERNEL_MAX_x32 and \
77 | cur.seccomp.v() > KERNEL_BASE_x32 and cur.seccomp.v() < KERNEL_MAX_x32 and \
78 | cur.pid >= 0 and cur.pid <= 0xffffffff and \
79 | cur.exit_state >= 0 and cur.exit_state <= 0xffffffff and \
80 | cur.state >= 0 and cur.state <= 0xffffffff and \
81 | cur.exit_code >= 0 and cur.exit_code <= 0xffffffff and \
82 | cur.signal > KERNEL_BASE_x32 and cur.signal < KERNEL_MAX_x32 and \
83 | cur.start_time.v() > KERNEL_BASE_x32 and cur.start_time.v() < KERNEL_MAX_x32 and \
84 | cur.se.cfs_rq > KERNEL_BASE_x32 and cur.se.cfs_rq < KERNEL_MAX_x32 and \
85 | cur.se.run_node.v() > KERNEL_BASE_x32 and cur.se.run_node.v() < KERNEL_MAX_x32 and \
86 | cur.se.statistics.v() > KERNEL_BASE_x32 and cur.se.statistics.v() < KERNEL_MAX_x32:
87 | yield cur
88 |
89 | def render_text(self, outfd, data):
90 | processes = {}
91 | proc_hits = {}
92 | for task in data:
93 | if task.pid not in processes:
94 | processes[task.pid] = task.comm
95 | proc_hits[task.pid] = 0
96 | else:
97 | proc_hits[task.pid] += 1
98 | procs = collections.OrderedDict(sorted(processes.items()))
99 | for k, v in procs.items():
100 | print "%d - %s" % (k, v)
101 | # Why some procs are so many times in memory? Cache?
102 | #for k, v in proc_hits.items():
103 | # print k, v
104 |
--------------------------------------------------------------------------------
/MichaelBrown/HOW_IT_WORKS.md:
--------------------------------------------------------------------------------
1 |
2 | How it Works
3 | ============
4 |
5 | Given a schema, it sqlitefind searches for a section of the row header that matches those types. The steps are:
6 |
7 | 1. Build needle - Based on column types given, figure out what to search for.
8 | 2. Search memory - Finds all instances of needle in memory.
9 | 3. Parse row - Perform checks to make sure this is actually row data. Return
10 | the data if it looks good.
11 |
12 | Build Needle
13 | ------------
14 |
15 | For details on database format, see: [SQLite Database File
16 | Format](https://www.sqlite.org/fileformat2.html)
17 |
18 | Each row in an sqlite database looks like this:
19 |
20 | Payload Length (varint)
21 | Row ID (varint)
22 | Header:
23 | Header Length (varint)
24 | Field 1 Serial Type (varint)
25 | Field 2 Serial Type (varint)
26 | ...
27 | Field 1 (size determined by corresponding type in header)
28 | Field 2 (size determined by corresponding type in header)
29 | ...
30 |
31 | The varint format is extensively used, which takes up 1 to 9 bytes and
32 | represents a 64-bit twos-compliment integer. The exact encoding is not
33 | important, you just need to know that varint encodes both its own length and an
34 | integer.
35 |
36 | The header defines how big each of the fields are by a number called the
37 | [Serial Type](https://www.sqlite.org/fileformat2.html#record_format). The
38 | fields follow immediately afterward. Some of the fields could be zero length
39 | too, like the Serial Types 0x08 and 0x09, which just mean the value is 0 or 1.
40 |
41 | The idea for building our needle is to search for the header based on prior
42 | information about the types the fields might have. There is one caveat to this:
43 | string and blob types can take up more than one byte in the header. Because the
44 | varint that stores strings and blobs also encode a length, they can take 1-9
45 | bytes. To get around this, we just search for the largest part of the header
46 | that has a fixed length. For example:
47 |
48 | bool; null,float; string; bool
49 | (08 | 09) (00 | 07) var length (08 | 09)
50 |
51 | The needle would be `(08 | 09) (00 | 07)`, because it's the longest part of the
52 | header that has fixed length. That means "either the byte 0x08 or 0x09,
53 | followed by either the byte 0x00 or 0x07".
54 |
55 | The routine that builds the needle also returns where the needle is relative to
56 | the beginning of the record. i.e. it specifies how many varints to count
57 | forwards or backwards and how many bytes to count forwards or backwards to get
58 | to the record. This is what allows the needle to be anywhere in the header. In
59 | the future it will be possible to have a needle located in the beginning of the
60 | actual column data.
61 |
62 | Search Memory
63 | -------------
64 |
65 | A yara rule is compiled for the needle so searching can be done quickly. The
66 | address space is broken into blocks and yara is called for each. There may be
67 | many matches of our needle that do not actually correspond to a row. False
68 | positives are (mostly) removed in the next step, but the number of yara matches
69 | greatly affects how fast the search is.
70 |
71 | Parse Row
72 | ---------
73 |
74 | Each match is given to the `parse_record` function, which either returns the
75 | data in the row, or raises an error. There are many checks to make sure the
76 | data is actually a row. The types are also checked, since the needle may not
77 | include all columns.
78 |
79 | sqlite_master Table
80 | -------------------
81 |
82 | The `sqlite_master` table is a special table in sqlite that stores the schemas
83 | for all other tables. The `sql` field stores the sql statement to create the
84 | table. The `sqlitefindtables` command searches for this table, then parses
85 | the sql to get the schema.
86 |
87 | The table looks like this:
88 |
89 | CREATE TABLE sqlite_master (
90 | type TEXT,
91 | name TEXT,
92 | tbl_name TEXT,
93 | rootpage INTEGER,
94 | sql TEXT
95 | );
96 |
97 | There is a slight problem with searching for this table though: every field
98 | except one is `TEXT`! Since there is only one field that has a fixed length in
99 | the header, our needle size will be 1, making this completely impractical.
100 |
101 | Fortunately, there is a better needle. For the kind of entries we're looking
102 | for, the `type` field is always "table". Our needle can just be "table", then
103 | we count backwards over all of the varints in the header to get to the
104 | beginning.
105 |
--------------------------------------------------------------------------------
/MichaelBrown/README 2.md:
--------------------------------------------------------------------------------
1 |
2 | SqliteFind is a Volatility plugin for finding sqlite database rows. It can automatically find database schemas in `sqlite_master` tables, and recover database rows from memory.
3 |
4 | * [Tutorial](TUTORIAL.md)
5 | * [How it works](HOW_IT_WORKS.md)
6 |
7 |
8 | Installing
9 | ==========
10 |
11 | "sqlitefind.py" must be in the plugin path and "sqlitetools.py" must be
12 | importable. You should either add this directory to your volatility plugin
13 | path, or add a link to these files inside the volatility plugin folder.
14 |
15 | Requires the YARA Python API. Try installing the pip package "yara-python".
16 | Running "import yara" should work in the Python shell.
17 |
18 |
19 | Basic Usage
20 | ===========
21 |
22 | Find tables:
23 |
24 | $ volatility -f sqlitefindtables
25 |
26 | Recover table rows:
27 |
28 | $ volatility -f sqlitefind -t
29 |
30 | For a guided tour, see the [Tutorial](TUTORIAL.md).
31 |
32 | See below for the common options, or use `--help` for a complete list of
33 | options.
34 |
35 |
36 | sqlitefindtables Command
37 | ========================
38 |
39 | Searches for an `sqlite_master` table and shows the schemas found in them.
40 |
41 | $ volatility -f sqlitefindtables
42 |
43 | Use `-R`/`--raw-sql` to output the schema in raw SQL.
44 |
45 |
46 | sqlitefind Command
47 | ==================
48 |
49 | Searches for database rows in memory, given the table schema. There are a few
50 | ways to specify the schema. You can specify the table name, in which case the
51 | schema matching the table name will be searched for in an `sqlite_master`
52 | table:
53 |
54 | $ volatility -f sqlitefind -t
55 |
56 | Alternatively, you can specify the table schema manually:
57 |
58 | $ volatility -f sqlitefind
59 | -c "id:int,null; place_name:string; visited:bool"
60 |
61 | Schema strings are output from `sqlitefindtables`, so you can just copy from
62 | there and modify if needed. Each column, separated by a semicolon, is a comma
63 | separated list of types. If a column starts with `name:`, then `name` is used
64 | as the column name. You can use the following types:
65 |
66 | * `?` - Specifies unknown, could be any type.
67 | * `bool` - Assumes schema format 4 or higher is used. If older schema, use
68 | "int8".
69 | * `null` - Fields cannot be NULL by default, don't forget to add this if
70 | needed.
71 | * `notnull` - Negates a previous "null".
72 | * `int`
73 | * `int` - `` must be one of 8, 16, 24, 32, 48, 64
74 | * `float`
75 | * `string` / `blob`
76 | * `timestamp` - Same as `int64`.
77 | * `` - A serial type number as defined by the [Sqlite file
78 | format](https://www.sqlite.org/fileformat2.html#record_format).
79 |
80 | One thing to notice is that **NULL is not allowed by default**. Make sure to
81 | add `null` to your type list if it is a possible value.
82 |
83 |
84 | Output Format
85 | -------------
86 |
87 | You can include different values in the output using the "-O" option, which is
88 | a comma separated list of:
89 |
90 | * `values` - A field for each sqlite column.
91 | * `all_values` - One field that is a list of every sqlite column.
92 | * `address` - Address the sqlite row was found in memory.
93 | * `all_types` - A list of types for each column in this row. Each type will
94 | be an integer serial type.
95 |
96 | For example, to show the memory address of the row followed by the values:
97 |
98 | $ volatility -f sqlitefind \
99 | -c "int,null; string; bool" \
100 | -O "address,all_values"
101 |
102 | CSV output is also supported, using "--output=csv":
103 |
104 | $ volatility -f sqlitefind \
105 | -c "id:int,null; field1:string; field2:bool" \
106 | -O "address,values" \
107 | --output=csv --output-file=data.csv
108 |
109 |
110 | Limitations
111 | ===========
112 |
113 | Needle Size - Based on the table schema, we may not be able to find a suitable
114 | sequence of bytes to search for. The smaller the needle size, the slower the
115 | search will take.
116 |
117 | Large Records - If a record does not fit in one B-Tree cell, it will be either
118 | missed or corrupted. This is because the rows are searched without using any
119 | database header information. If a row is large enough to be split between
120 | multiple pages, we can only find the data from the first page. After that,
121 | we will either read garbage data, or encounter an error and assume that it's
122 | not a real row.
123 |
124 | False positives - There are a lot of checks to make the data parsed is actually
125 | a row, but especially when there are not many columns, false positives can be
126 | found. Usually false positives are easy to recognize by hand. They typically
127 | contain many NULL values (None) and strings will contain nonsensical data.
128 |
129 |
130 | About
131 | =====
132 |
133 | Written by Michael Brown as a project for the Computer Forensics class taught
134 | by Fabian Monrose at the University of North Carolina Chapel Hill. Feel free to contact me at [michael@msbrown.net](mailto:michael@msbrown.net), or start an issue on [GitHub](https://github.com/mbrown1413/SqliteFind).
135 |
136 | The idea of searching for sqlite database rows in memory is based on Dave
137 | Lassalle's (@superponible) [firefox volatility
138 | plugins](https://github.com/superponible/volatility-plugins), which can find
139 | firefox and chromium data in memory. I wanted to generalize the idea so no code
140 | would need to be updated when a schema changes, and any sqlite database could
141 | be recovered.
142 |
--------------------------------------------------------------------------------
/MichaelBrown/README.md:
--------------------------------------------------------------------------------
1 | Author: Michael Brown
2 |
3 | See https://github.com/mbrown1413/SqliteFind for updates and license information.
--------------------------------------------------------------------------------
/MichaelBrown/TODO:
--------------------------------------------------------------------------------
1 |
2 | Bugs:
3 | "yara.Error: internal error: 30" - This happens when there are more than 1000000 matches in a block.
4 | I plan on making a match function that catches error 30 and splits the buffer into two until the error doesn't happen.
5 |
6 | Features:
7 | Allow custom needles in PREDEFINED_TABLES.
8 | Automatically find table schemas:
9 | No arguments to sqlitefind will do 2 passes: find all table definitions, then find all matching table rows.
10 | -t argument finds the table definition for and searches for that.
11 | Needle sizes smaller than 2 are not used.
12 | print 'Ignoring table "{}" with needle size {}. Use --min-needle-size to enable smaller needles.'
13 | Option --min-needle-size
14 | PREDEFINED_TABLES for:
15 | firefox
16 | google chrome
17 | Option to input sql schema instead of schema string.
18 |
19 | Documentation:
20 | Describe table schema schemes more completely
21 | More of how it works
22 |
23 | Optimization:
24 | Allow RowSearch to search for more than one table at once.
25 |
26 | Correctness:
27 | String encodings?
28 | What happens when the header contains a negative varint?
29 |
30 | Sqlite Tools Features:
31 | Forwards varint counting
32 | Encoding multibyte varints
33 | Encoding negative varints
34 | Allow RowSearch on plain buffer
35 | Make yara/volatility optional imports
36 |
37 | SQL Parsing Types:
38 | varchar(%d)
39 | timestamp
40 | datetime
41 | FOREIGN KEY () REFERENCES (, ...)
42 | CONSTRAINT UNIQUE (, ...)
43 | PRIMARY KEY (, ...)
44 | Tables without any types:
45 | CREATE TABLE sqlite_sequence (name, seq);
46 | CREATE TABLE sqlite_stat1 (tbl1, idx, stat);
47 |
--------------------------------------------------------------------------------
/MichaelBrown/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/MichaelBrown/analysis/README.md:
--------------------------------------------------------------------------------
1 |
2 | This is a rough quantitative analysis of how well `sqlitefind` can recover
3 | database rows.
4 |
5 | Data files are in the `data/` directory. The large files like memory dumps and
6 | databases are not in the repository. **You can download the large files
7 | [here](https://msbrown.net/sqlitefind/).**
8 |
9 | Memory dumps were accomplished using virsh dump:
10 |
11 | # virsh dump --domain --memory-only --file .img
12 |
13 |
14 | Test Database
15 | =============
16 |
17 | Gathering Data
18 | --------------
19 |
20 | 1. Create database `test_db.sqlite` using `create_test_db.py` script.
21 | 2. Reboot Ubuntu VM.
22 | 3. Open `test_db.sqlite` with the `sqlite3` command.
23 | 4. Execute "SELECT * FROM TESTTABLE;".
24 | 5. Take memory snapshot.
25 |
26 | Data files:
27 |
28 | * `testdb_snapshot.img` - Memory snapshot
29 | * `test_db.sqlite` - Database file
30 |
31 | Analysis
32 | --------
33 |
34 | Files generated:
35 |
36 | * `recovered_testtable.csv`
37 |
38 | The `sqlitefindtables` command correctly finds the schema for the table "testtable":
39 |
40 | $ volatility --profile=LinuxUbuntu16045x64
41 | -f data/testdb_snapshot.img sqlitefindtables
42 | Name Column Type String
43 | ...
44 | testtable id:null,int; i:int; even:bool,null; odd:bool,null; s:string,null
45 | ...
46 |
47 | Entering the schema into the `sqlitefind` command we can recover the rows:
48 |
49 | $ volatility --profile=LinuxUbuntu16045x64 \
50 | -f data/testdb_snapshot.img sqlitefind \
51 | -c "id:null,int; i:int; even:bool,null; odd:bool,null; s:string,null" \
52 | --output=csv --output-file=data/recovered_testtable.csv
53 | Outputting to: data/recovered_testtable.csv
54 | Needle Size: 4
55 |
56 | How many of the rows did we recover?
57 |
58 | $ wc -l data/recovered_testtable.csv
59 | 1048
60 |
61 | Subtracting out the CSV header, we found 1047 rows. Our database has 1000 rows
62 | in it, so how many actually look like data we inserted?
63 |
64 | $ grep "This is testtable row" data/recovered_testtable.csv | wc -l
65 | 1001
66 |
67 | That's strange, we found an extra row! The culprit is one spurious row that
68 | ends with garbage data (here, the syntax `\0xaa` means the byte `0xaa`):
69 |
70 | "347","347","0","1","This is testtable row 3\0xc3\0x97\0xc3\0xbf"
71 |
72 | What about things that don't look like our data:
73 |
74 | $ grep -v "This is testtable row" data/recovered_testtable.csv | wc -l
75 | 47
76 |
77 | Most of these are found because there are places in memory that look like a
78 | database row, but are't. NULL is a particularly common value because the serial
79 | type for NULL is 0x00. There could also be a table in memory with a similar
80 | schema that we find. In a table with few columns like this, spurious matches
81 | are also more likely. In any case, these spurious matches usually don't look
82 | like interesting data to a human.
83 |
84 | Final result:
85 |
86 | * 1047 Rows found
87 | * 1000 / 1000 True positives found
88 | * 47 False Positives
89 |
90 |
91 | Fresh Boot
92 | ==========
93 |
94 | An Ubuntu12.04 VM was booted to the GUI and then a memory snapshot was taken to
95 | see what we find without explicitly opening a database. See
96 | `data/fresh_boot.img`.
97 |
98 | Interestingly, we can find an sqlite database in memory after startup:
99 |
100 | $ volatility -f data/fresh_boot.img sqlitefindtables
101 | Name Column Type String
102 | uri id:null,int; value:string,null
103 | interpretation id:null,int; value:string,null
104 | manifestation id:null,int; value:string,null
105 | payload id:null,int; value:blob,null
106 | storage id:null,int; value:string,null; state:null,int;
107 | icon:string,null; display_name:string,null
108 | text id:null,int; value:string,null
109 | mimetype id:null,int; value:string,null
110 | actor id:null,int; value:string,null
111 | schema_version schema:string,null; version:null,int
112 | mappings timestamp:null,int; device:string,null; profile:string,null
113 | properties device_id:string,null; property:string,null; value:string,null
114 | devices device_id:string,null; device:string,null
115 |
116 | The database might have something to do with the GUI, or another service that
117 | runs on startup. To find out, you could print the offsets in memory that the
118 | table schemas were found, then map that back to a process.
119 |
120 | There's currently a limitation that keeps us from searching for these rows
121 | though. Every one of them has a needle size of one byte, which would take a
122 | long time to search. YARA raises an error if we have more than 1000000 matches
123 | in one search, and currently the searching is done in blocks of 10 kilobytes.
124 | This can result in too many matches with small needles. More work is needed to
125 | make searching for small needles work.
126 |
--------------------------------------------------------------------------------
/MichaelBrown/analysis/create_test_db.py:
--------------------------------------------------------------------------------
1 |
2 | import sys
3 |
4 | import sqlite3
5 |
6 | def main():
7 | dbname = sys.argv[1]
8 |
9 | with sqlite3.connect(dbname) as con:
10 | cur = con.cursor()
11 |
12 | cur.execute('DROP TABLE IF EXISTS testtable')
13 | cur.execute('CREATE TABLE testtable (id INT, i INT NOT NULL, even BOOLEAN, odd BOOLEAN, s TEXT)')
14 |
15 | for i in range(1000):
16 | text = "This is testtable row {}".format(i)
17 | cur.execute('INSERT INTO testtable VALUES (?, ?, ?, ?, ?)',
18 | (i, i, i%2==0, i%2==1, text))
19 |
20 | if __name__ == "__main__":
21 | main()
22 |
--------------------------------------------------------------------------------
/MichaelBrown/analysis/data/firefox_recovered_places.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/MichaelBrown/analysis/data/firefox_recovered_places.csv
--------------------------------------------------------------------------------
/MichaelBrown/analysis/data/firefox_tables.csv:
--------------------------------------------------------------------------------
1 | Name, Column Type String
2 | "uri","id:null,int; value:string,null"
3 | "interpretation","id:null,int; value:string,null"
4 | "manifestation","id:null,int; value:string,null"
5 | "payload","id:null,int; value:blob,null"
6 | "storage","id:null,int; value:string,null; state:null,int; icon:string,null; display_name:string,null"
7 | "text","id:null,int; value:string,null"
8 | "mimetype","id:null,int; value:string,null"
9 | "actor","id:null,int; value:string,null"
10 | "schema_version","schema:string,null; version:null,int"
11 | "moz_downloads","id:null,int; name:string,null; source:string,null; target:string,null; tempPath:string,null; startTime:null,int; endTime:null,int; state:null,int; referrer:string,null; entityID:string,null; currBytes:int; maxBytes:int; mimeType:string,null; preferredApplication:string,null; preferredAction:int; autoResume:int; guid:string,null"
12 | "moz_deleted_logins","id:null,int; guid:string,null; timeDeleted:null,int"
13 | "moz_disabledHosts","id:null,int; hostname:string,null"
14 | "moz_logins","id:null,int; hostname:string; httpRealm:string,null; formSubmitURL:string,null; usernameField:string; passwordField:string; encryptedUsername:string; encryptedPassword:string; guid:string,null; encType:null,int; timeCreated:null,int; timeLastUsed:null,int; timePasswordChanged:null,int; timesUsed:null,int"
15 | "moz_keywords","id:null,int; keyword:string,null"
16 | "moz_bookmarks","id:null,int; type:null,int; fk:null,int; parent:null,int; position:null,int; title:string,null; keyword_id:null,int; folder_type:string,null; dateAdded:null,int; lastModified:null,int; guid:string,null"
17 | "moz_hosts","id:null,int; host:string; frecency:null,int; typed:int; prefix:string,null"
18 | "moz_historyvisits","id:null,int; from_visit:null,int; place_id:null,int; visit_date:null,int; visit_type:null,int; session:null,int"
19 | "moz_places","id:null,int; url:string,null; title:string,null; rev_host:string,null; visit_count:null,int; hidden:int; typed:int; favicon_id:null,int; frecency:int; last_visit_date:null,int; guid:string,null"
20 | "expiration_notify","id:null,int; v_id:null,int; p_id:null,int; url:string; guid:string; visit_date:null,int; expected_results:int"
21 | "prefs","id:null,int; groupID:null,int; settingID:int; value:blob,null"
22 | "settings","id:null,int; name:string"
23 | "groups","id:null,int; name:string"
24 | "webappsstore2","scope:string,null; key:string,null; value:string,null; secure:null,int; owner:string,null"
25 | "mappings","timestamp:null,int; device:string,null; profile:string,null"
26 | "properties","device_id:string,null; property:string,null; value:string,null"
27 | "devices","device_id:string,null; device:string,null"
28 | "moz_deleted_formhistory","id:null,int; timeDeleted:null,int; guid:string,null"
29 | "moz_formhistory","id:null,int; fieldname:string; value:string; timesUsed:null,int; firstUsed:null,int; lastUsed:null,int; guid:string,null"
30 | "moz_openpages_temp","url:string,null; open_count:null,int"
31 | "moz_hosts","id:null,int; host:string,null; type:string,null; permission:null,int; expireType:null,int; expireTime:null,int; appId:null,int; isInBrowserElement:null,int"
32 |
--------------------------------------------------------------------------------
/MichaelBrown/analysis/data/firefox_tables_sql.csv:
--------------------------------------------------------------------------------
1 | Name, SQL
2 | "uri","CREATE TABLE uri (
3 | id INTEGER PRIMARY KEY,
4 | value VARCHAR UNIQUE
5 | )"
6 | "interpretation","CREATE TABLE interpretation (
7 | id INTEGER PRIMARY KEY AUTOINCREMENT,
8 | value VARCHAR UNIQUE
9 | )"
10 | "manifestation","CREATE TABLE manifestation (
11 | id INTEGER PRIMARY KEY AUTOINCREMENT,
12 | value VARCHAR UNIQUE
13 | )"
14 | "payload","CREATE TABLE payload
15 | (id INTEGER PRIMARY KEY, value BLOB)"
16 | "storage","CREATE TABLE storage (
17 | id INTEGER PRIMARY KEY,
18 | value VARCHAR UNIQUE,
19 | state INTEGER,
20 | icon VARCHAR,
21 | display_name VARCHAR
22 | )"
23 | "text","CREATE TABLE text (
24 | id INTEGER PRIMARY KEY,
25 | value VARCHAR UNIQUE
26 | )"
27 | "mimetype","CREATE TABLE mimetype (
28 | id INTEGER PRIMARY KEY AUTOINCREMENT,
29 | value VARCHAR UNIQUE
30 | )"
31 | "actor","CREATE TABLE actor (
32 | id INTEGER PRIMARY KEY AUTOINCREMENT,
33 | value VARCHAR UNIQUE
34 | )"
35 | "schema_version","CREATE TABLE schema_version (
36 | schema VARCHAR PRIMARY KEY ON CONFLICT REPLACE,
37 | version INT
38 | )"
39 | "moz_downloads","CREATE TABLE moz_downloads (id INTEGER PRIMARY KEY, name TEXT, source TEXT, target TEXT, tempPath TEXT, startTime INTEGER, endTime INTEGER, state INTEGER, referrer TEXT, entityID TEXT, currBytes INTEGER NOT NULL DEFAULT 0, maxBytes INTEGER NOT NULL DEFAULT -1, mimeType TEXT, preferredApplication TEXT, preferredAction INTEGER NOT NULL DEFAULT 0, autoResume INTEGER NOT NULL DEFAULT 0, guid TEXT)"
40 | "moz_deleted_logins","CREATE TABLE moz_deleted_logins (id INTEGER PRIMARY KEY,guid TEXT,timeDeleted INTEGER)"
41 | "moz_disabledHosts","CREATE TABLE moz_disabledHosts (id INTEGER PRIMARY KEY,hostname TEXT UNIQUE ON CONFLICT REPLACE)"
42 | "moz_logins","CREATE TABLE moz_logins (id INTEGER PRIMARY KEY,hostname TEXT NOT NULL,httpRealm TEXT,formSubmitURL TEXT,usernameField TEXT NOT NULL,passwordField TEXT NOT NULL,encryptedUsername TEXT NOT NULL,encryptedPassword TEXT NOT NULL,guid TEXT,encType INTEGER,timeCreated INTEGER,timeLastUsed INTEGER,timePasswordChanged INTEGER,timesUsed INTEGER)"
43 | "moz_keywords","CREATE TABLE moz_keywords ( id INTEGER PRIMARY KEY AUTOINCREMENT, keyword TEXT UNIQUE)"
44 | "moz_bookmarks","CREATE TABLE moz_bookmarks ( id INTEGER PRIMARY KEY, type INTEGER, fk INTEGER DEFAULT NULL, parent INTEGER, position INTEGER, title LONGVARCHAR, keyword_id INTEGER, folder_type TEXT, dateAdded INTEGER, lastModified INTEGER, guid TEXT)"
45 | "moz_hosts","CREATE TABLE moz_hosts ( id INTEGER PRIMARY KEY, host TEXT NOT NULL UNIQUE, frecency INTEGER, typed INTEGER NOT NULL DEFAULT 0, prefix TEXT)"
46 | "moz_historyvisits","CREATE TABLE moz_historyvisits ( id INTEGER PRIMARY KEY, from_visit INTEGER, place_id INTEGER, visit_date INTEGER, visit_type INTEGER, session INTEGER)"
47 | "moz_places","CREATE TABLE moz_places ( id INTEGER PRIMARY KEY, url LONGVARCHAR, title LONGVARCHAR, rev_host LONGVARCHAR, visit_count INTEGER DEFAULT 0, hidden INTEGER DEFAULT 0 NOT NULL, typed INTEGER DEFAULT 0 NOT NULL, favicon_id INTEGER, frecency INTEGER DEFAULT -1 NOT NULL, last_visit_date INTEGER , guid TEXT)"
48 | "expiration_notify","CREATE TABLE expiration_notify ( id INTEGER PRIMARY KEY , v_id INTEGER , p_id INTEGER , url TEXT NOT NULL , guid TEXT NOT NULL , visit_date INTEGER , expected_results INTEGER NOT NULL )"
49 | "prefs","CREATE TABLE prefs (id INTEGER PRIMARY KEY, groupID INTEGER REFERENCES groups(id), settingID INTEGER NOT NULL REFERENCES settings(id), value BLOB)"
50 | "settings","CREATE TABLE settings (id INTEGER PRIMARY KEY, name TEXT NOT NULL)"
51 | "groups","CREATE TABLE groups (id INTEGER PRIMARY KEY, name TEXT NOT NULL)"
52 | "webappsstore2","CREATE TABLE webappsstore2 (scope TEXT, key TEXT, value TEXT, secure INTEGER, owner TEXT)"
53 | "mappings","CREATE TABLE mappings (timestamp INTEGER DEFAULT 0,device TEXT,profile TEXT)"
54 | "properties","CREATE TABLE properties (device_id TEXT,property TEXT,value TEXT)"
55 | "devices","CREATE TABLE devices (device_id TEXT PRIMARY KEY,device TEXT)"
56 | "moz_deleted_formhistory","CREATE TABLE moz_deleted_formhistory (id INTEGER PRIMARY KEY, timeDeleted INTEGER, guid TEXT)"
57 | "moz_formhistory","CREATE TABLE moz_formhistory (id INTEGER PRIMARY KEY, fieldname TEXT NOT NULL, value TEXT NOT NULL, timesUsed INTEGER, firstUsed INTEGER, lastUsed INTEGER, guid TEXT)"
58 | "moz_openpages_temp","CREATE TABLE moz_openpages_temp ( url TEXT PRIMARY KEY , open_count INTEGER )"
59 | "moz_hosts","CREATE TABLE moz_hosts ( id INTEGER PRIMARY KEY,host TEXT,type TEXT,permission INTEGER,expireType INTEGER,expireTime INTEGER,appId INTEGER,isInBrowserElement INTEGER)"
60 |
--------------------------------------------------------------------------------
/MichaelBrown/analysis/data/recovered_testtable.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/MichaelBrown/analysis/data/recovered_testtable.csv
--------------------------------------------------------------------------------
/MikeAuty/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/MikeAuty/__init__.py
--------------------------------------------------------------------------------
/MikeAuty/scanprof.py:
--------------------------------------------------------------------------------
1 | # Volatility
2 | #
3 | # Authors:
4 | # Mike Auty
5 | #
6 | # This file is part of Volatility.
7 | #
8 | # Volatility is free software; you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation; either version 2 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # Volatility is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with Volatility. If not, see .
20 | #
21 |
22 | import sys
23 | import itertools
24 | import timeit
25 |
26 | class ScanProfInstance(object):
27 | def __init__(self, func, *args):
28 | self.func = func
29 | self.args = args
30 | self.results = []
31 |
32 | def __call__(self):
33 | self.results = self.func(*self.args)
34 |
35 | def permscan(self, address_space, offset = 0, maxlen = None):
36 | times = []
37 | # Run a warm-up scan to ensure the file is cached as much as possible
38 | self.oldscan(address_space, offset, maxlen)
39 |
40 | perms = list(itertools.permutations(self.checks))
41 | for i in range(len(perms)):
42 | self.checks = perms[i]
43 | print "Running scan {0}/{1}...".format(i + 1, len(perms))
44 | profobj = ScanProfInstance(self.oldscan, address_space, offset, maxlen)
45 | value = timeit.timeit(profobj, number = self.repeats)
46 | times.append((value, len(list(profobj.results)), i))
47 |
48 | print "Scan results"
49 | print "{0:20} | {1:7} | {2:6} | {3}".format("Time", "Results", "Perm #", "Ordering")
50 | for val, l, ordering in sorted(times):
51 | print "{0:20} | {1:7} | {2:6} | {3}".format(val, l, ordering, perms[ordering])
52 | sys.exit(1)
53 |
54 | def ScanProfiler(cls, repeats = 3):
55 | cls.repeats = repeats
56 | cls.oldscan = cls.scan
57 | cls.scan = permscan
58 | return cls
59 |
--------------------------------------------------------------------------------
/MonnappaKa/README.md:
--------------------------------------------------------------------------------
1 | Author: Monnappa Ka
2 |
3 | (At this time, the author is not known to have a GitHub profile page)
--------------------------------------------------------------------------------
/MonnappaKa/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/NCCGroup/README.md:
--------------------------------------------------------------------------------
1 | Author: NCC Group (Ollie Whitehouse)
2 |
3 | See https://github.com/nccgroup for updates and license information.
--------------------------------------------------------------------------------
/NCCGroup/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/NichlasHolm/README.md:
--------------------------------------------------------------------------------
1 | Author: Nichlas Holm
2 |
3 | See https://github.com/Memoryforensics for updates and licensing information.
--------------------------------------------------------------------------------
/NichlasHolm/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/NickGk/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Nikos Gk
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/NickGk/README.md:
--------------------------------------------------------------------------------
1 | Author: Nick Gk
2 |
3 | See https://github.com/ngkogkos for updates and license information.
--------------------------------------------------------------------------------
/NickGk/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/PSDispScan/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/PSDispScan/__init__.py
--------------------------------------------------------------------------------
/PageCheck/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/PageCheck/__init__.py
--------------------------------------------------------------------------------
/PageCheck/pagecheck.py:
--------------------------------------------------------------------------------
1 | # Volatility
2 | #
3 | # This file is part of Volatility.
4 | #
5 | # Volatility is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Volatility is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Volatility. If not, see .
17 | #
18 |
19 | import volatility.commands as commands
20 | import volatility.utils as utils
21 |
22 | class PageCheck(commands.Command):
23 | """Reads the available pages and reports if any are inaccessible"""
24 |
25 | def render_text(self, outfd, data):
26 | """Displays any page errors"""
27 | found = False
28 | for page, vtop, size, pde, pte in data:
29 | found = True
30 | outfd.write("(V): 0x{0:08x} [PDE] 0x{3:08x} [PTE] 0x{4:08x} (P): 0x{1:08x} Size: 0x{2:08x}\n".format(page, vtop, size, pde, pte))
31 | if not found:
32 | outfd.write("No page failures found!")
33 |
34 | def calculate(self):
35 | """Calculate returns the results of the available pages validity"""
36 | addr_space = utils.load_as(self._config)
37 | for page, size in addr_space.get_available_pages():
38 | output = addr_space.read(page, size)
39 | if output == None:
40 | pde_value = addr_space.get_pde(page)
41 | pte_value = addr_space.get_pte(page, pde_value)
42 | yield page, addr_space.vtop(page), size, pde_value, pte_value
43 |
--------------------------------------------------------------------------------
/PeterCasey/README.md:
--------------------------------------------------------------------------------
1 | # vive-dump
2 | Volatility Plugin to extract VR device information.
3 | Searches memory for the chaperone configuration file. Converts and dumps the file chaperone_vis.obj
4 |
5 | ### Usage
6 | Example `python .\vol.py --plugin vive-dump -f dump.dmp --profile Win10x64_16299 vivedump -N 5`
7 | * -C --CHAP-FILE Provide Chaperone config file to visualizer (if not found in memory)
8 | * -F --FULL-SCAN Scan the entire dump file, default only scans vrmonitor.exe
9 | * -N --NUM_DEVICES To specify the number of tracked devices to extract
10 | * -V --NO-VIS Turn of Visualization
11 |
12 | * left/right arrows: move camera along x axis
13 | * up/down arrows: move camera along y axis
14 | * quote / forward slash: move camera along z axis
15 | 
16 | * Red = HMD
17 | * Green = Controllers
18 | * Blue = Base Stations
19 |
20 | ### Dependancies:
21 | * Yara, make sure you download from the developer site and not pip [here](http://yara.readthedocs.io/en/v3.7.0/gettingstarted.html)
22 | * json `python -m pip install json`
23 | * pygame `python -m pip install pygame`
24 | * opengl `python -m pip install PyOpenGL PyOpenGL_accelerate`
25 | * Need the latest release of volatility. Use the profile `Win10x64_16299`
26 |
27 | ### TODOs:
28 | * Need to be able to detect Steam VR Version, so we know which Yara rules and offsets to use
29 | * Find other information about the controllers, eg. Serial #, Firmware, that kind of stuff
30 |
31 | ### References:
32 | [Link to convert to quaternion](https://www.codeproject.com/Articles/1171122/WebControls/)
33 |
34 | [How to traverse the Vad with yara](http://tomchop.me/2016/11/21/tutorial-volatility-plugins-malware-analysis/)
35 |
36 | [Filescan](https://github.com/volatilityfoundation/community/blob/58d36880ae35e4de00d80694d54c4cae278b21c7/ThomasChopitea/autoruns.py)
37 |
38 | [Code for Yara scan](https://github.com/volatilityfoundation/community/blob/58d36880ae35e4de00d80694d54c4cae278b21c7/KudelskiSecurity/dyrescan.py)
39 |
40 | [Template](https://gist.github.com/bridgeythegeek/bf7284d4469b60b8b9b3c4bfd03d051e)
41 |
--------------------------------------------------------------------------------
/PeterCasey/vis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/PeterCasey/vis.png
--------------------------------------------------------------------------------
/PeterCasey/visualizer.py:
--------------------------------------------------------------------------------
1 | """Here goes the opengl stuff"""
2 |
3 | import pygame
4 | from pygame.locals import *
5 | from OpenGL.GL import *
6 | from OpenGL.GLU import *
7 |
8 | key_sens = 0.4
9 |
10 | # The Chaperone vertices and edges, received from vivedump.build_obj()
11 | chap_vert = []
12 | chap_edges = []
13 |
14 | # List of tracked devices to draw
15 | # (matrix4x4, type)
16 | devices = []
17 |
18 | # Defines the edges in a cube
19 | cube_edge = [
20 | (0, 1),
21 | (1, 2),
22 | (2, 3),
23 | (3, 0),
24 | (4, 5),
25 | (5, 6),
26 | (6, 7),
27 | (7, 3),
28 | (7, 4),
29 | (1, 5),
30 | (2, 6),
31 | (0, 4)
32 | ]
33 |
34 | def get_rect(width, height, depth):
35 | """ Enter half the width height and depth you would like """
36 | return [
37 | (width, height, depth),
38 | (-width, height, depth),
39 | (-width, -height, depth),
40 | (width, -height, depth),
41 | (width, height, -depth),
42 | (-width, height, -depth),
43 | (-width, -height, -depth),
44 | (width, -height, -depth),
45 | ]
46 |
47 |
48 | class Vis:
49 |
50 | # Starting camera location
51 | cam_x = 0
52 | cam_y = 7
53 | cam_z = -7
54 |
55 | def add_vert(self, x, y, z):
56 | chap_vert.append((x, y, z))
57 |
58 | def add_edge(self, i, j):
59 | chap_edges.append((i, j))
60 |
61 | def set_device(self, x, type):
62 | devices.append((x, type))
63 |
64 | def __init__(self):
65 | self._running = True
66 | self._display_surf = None
67 | self.size = self.weight, self.height = 1280, 800
68 |
69 | def on_init(self):
70 | pygame.init()
71 | self._display_surf = pygame.display.set_mode(self.size, DOUBLEBUF | OPENGL )
72 | self._running = True
73 | gluPerspective(45, (self.size[0] / self.size[1]), 0.1, 50.0)
74 | gluLookAt(self.cam_x, self.cam_y, self.cam_z, 0, 0, 0, 0, 1, 0)
75 |
76 | def on_event(self, event):
77 | if event.type == pygame.QUIT:
78 | self._running = False
79 |
80 | # Camera movements
81 | if event.type == pygame.KEYUP:
82 | if event.key == pygame.K_LEFT:
83 | self.cam_x -= key_sens
84 | elif event.key == pygame.K_RIGHT:
85 | self.cam_x += key_sens
86 | elif event.key == pygame.K_UP:
87 | self.cam_y += key_sens
88 | elif event.key == pygame.K_DOWN:
89 | self.cam_y -= key_sens
90 | elif event.key == pygame.K_QUOTE:
91 | self.cam_z += key_sens
92 | elif event.key == pygame.K_SLASH:
93 | self.cam_z -= key_sens
94 |
95 | # Reload new perpective
96 | glLoadIdentity()
97 | gluPerspective(45, (self.size[0] / self.size[1]), 0.1, 50.0)
98 | gluLookAt(self.cam_x, self.cam_y, self.cam_z, 0, 0, 0, 0, 1, 0)
99 |
100 | def on_loop(self):
101 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
102 | self.draw_chaperone()
103 | self.draw_devices()
104 |
105 | def on_render(self):
106 | pygame.display.flip()
107 |
108 | def on_cleanup(self):
109 | pygame.quit()
110 |
111 | def on_execute(self):
112 | if self.on_init() == False:
113 | self._running = False
114 |
115 | while (self._running):
116 | for event in pygame.event.get():
117 | self.on_event(event)
118 | self.on_loop()
119 | self.on_render()
120 | self.on_cleanup()
121 |
122 | def draw_chaperone(self):
123 | glColor3f(1.0, 1.0, 1.0)
124 | glBegin(GL_LINES)
125 | for edge in chap_edges:
126 | for vertex in edge:
127 | glVertex3fv(chap_vert[vertex])
128 | glEnd()
129 |
130 | def draw_devices(self):
131 | for d in devices:
132 | # Set the appropriate size and color for each device type
133 | if d[1] == 'HMD':
134 | rectangle = get_rect(0.1, 0.06, 0.06)
135 | glColor3f(1.0, 0.0, 0.0) # Red
136 | elif d[1] == 'Controller':
137 | rectangle = get_rect(0.01, 0.01, 0.1)
138 | glColor3f(0.0, 1.0, 0.0) # Green
139 | else:
140 | rectangle = get_rect(0.05, 0.05, 0.01)
141 | glColor3f(0.0, 0.0, 1.0) # Blue
142 |
143 | glPushMatrix()
144 | glMultMatrixf(d[0])
145 | glBegin(GL_LINES)
146 | for edge in cube_edge:
147 | for vertex in edge:
148 | glVertex3fv(rectangle[vertex])
149 |
150 | # Draw line to show front face
151 | glVertex3f(0, 0, 0)
152 | glVertex3f(0, 0, -0.08)
153 | glEnd()
154 | glPopMatrix()
155 |
--------------------------------------------------------------------------------
/PhilipHuppert/README.md:
--------------------------------------------------------------------------------
1 | Author: Philip Huppert
2 |
3 | See https://github.com/Phaeilo for updates and license information.
--------------------------------------------------------------------------------
/PhilipHuppert/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/PhilipHuppert/openvpn.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python2
2 | # coding=utf-8
3 |
4 | """Volatility plugin to extract OpenVPN credentials cached in memory."""
5 |
6 | import struct
7 | import string
8 | import volatility.plugins.common as common
9 | import volatility.obj as obj
10 | import volatility.utils as utils
11 | import volatility.win32.tasks as tasks
12 |
13 | __author__ = "Philip Huppert"
14 | __copyright__ = "Copyright 2014, Philip Huppert"
15 | __license__ = "MIT"
16 |
17 |
18 | USERNAME_CHARSET = string.ascii_letters + string.digits + "_-.@"
19 |
20 |
21 | def valid_bool(x):
22 | return 0 <= x <= 1
23 |
24 |
25 | def terminate_string(s):
26 | s, _, _ = s.partition("\0")
27 | return s
28 |
29 |
30 | class OpenVPN(common.AbstractWindowsCommand):
31 | """Extract OpenVPN client credentials (username, password) cached in memory.
32 |
33 | This extractor supports OpenVPN 2.X.X on Windows. It was successfully tested with OpenVPN 2.2.2, 2.3.2 and 2.3.4
34 | on Windows XP (x86) and Windows 7 (x86 & x64). Credentials are available in memory if the client authenticated with
35 | a username & password or entered a password to unlock a private key. Furthermore, OpenVPN's --auth-nocache flag
36 | must not be set.
37 | """
38 |
39 | def calculate(self):
40 | """Search memory for credentials"""
41 |
42 | kernel_memory = utils.load_as(self._config)
43 |
44 | # Find all OpenVPN processes
45 | processes = tasks.pslist(kernel_memory)
46 | processes = filter(lambda p: str(p.ImageFileName).lower() == "openvpn.exe", processes)
47 |
48 | # Search for credentials in each process
49 | for process in processes:
50 | process_memory = process.get_process_address_space()
51 |
52 | # Get some basic process information
53 | pid = int(process.UniqueProcessId)
54 | image_base = process.Peb.ImageBaseAddress
55 | dos_header = obj.Object("_IMAGE_DOS_HEADER", offset=image_base, vm=process_memory)
56 | nt_header = dos_header.get_nt_header()
57 |
58 | # Find the .data and .bss sections
59 | sections = nt_header.get_sections(True)
60 | sections = filter(lambda s: str(s.Name) in [".data", ".bss"], sections)
61 | if len(sections) == 0:
62 | # Sections may be unavailable
63 | continue
64 |
65 | # Search each section for credentials
66 | for section in sections:
67 | # Determine dimensions of section
68 | sec_start = section.VirtualAddress + image_base
69 | sec_end = sec_start + section.Misc.VirtualSize
70 | sec_type = str(section.Name)
71 |
72 | # Search static user_pass struct
73 | # Assumptions:
74 | # - Struct is aligned on 16-byte boundary
75 | # - Bool fields are 4 bytes long in 2.2.2
76 | # - Bool fields are 2 bytes long in 2.3.2 and 2.3.4
77 | # - Username and password buffers are 4096 bytes long
78 | for creds_start in xrange(sec_start, sec_end, 16):
79 | creds = process_memory.read(creds_start, 16)
80 | if not creds:
81 | # Memory may be unavailable
82 | continue
83 |
84 | struct_layout = None
85 | struct_length = None
86 |
87 | # Detect the 2.2.2 struct
88 | defined, nocache, username = struct.unpack("II8s", creds)
89 | if sec_type == ".data" \
90 | and valid_bool(defined) \
91 | and valid_bool(nocache) \
92 | and username[0] in USERNAME_CHARSET:
93 | struct_layout = "II4096s4096s"
94 | struct_length = 4 + 4 + 4096 + 4096
95 |
96 | # Detect the 2.3.2/2.3.4 struct
97 | defined, nocache, username = struct.unpack("BB14s", creds)
98 | if sec_type == ".bss" \
99 | and valid_bool(defined) \
100 | and valid_bool(nocache) \
101 | and username[0] in USERNAME_CHARSET:
102 | struct_layout = "BB4096s4096s"
103 | struct_length = 1 + 1 + 4096 + 4096
104 |
105 | if struct_layout is not None:
106 | # Read and parse detected structure
107 | creds = process_memory.zread(creds_start, struct_length)
108 |
109 | _, _, username, password = struct.unpack(struct_layout, creds)
110 |
111 | # Terminate strings at null byte
112 | username = terminate_string(username)
113 | password = terminate_string(password)
114 | yield (pid, username, password)
115 |
116 | # Stop searching in current section
117 | break
118 |
119 | def render_text(self, outfd, data):
120 | """Display credentials."""
121 |
122 | self.table_header(outfd, [
123 | ("Pid", "8"),
124 | ("Username", "32"),
125 | ("Password", "32")])
126 |
127 | for (pid, username, password) in data:
128 | self.table_row(outfd, pid, username, password)
129 |
--------------------------------------------------------------------------------
/PhilipHuppert/rsakey.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding=utf-8
3 |
4 | """Volatility plugin to extract base64/PEM encoded private RSA keys from
5 | physical memory.
6 |
7 | """
8 |
9 | import volatility.plugins.common as common
10 | import volatility.utils as utils
11 |
12 | START_MARKER = "-----BEGIN RSA PRIVATE KEY-----"
13 | END_MARKER = "-----END RSA PRIVATE KEY-----"
14 | CHUNK_SIZE = 10240
15 |
16 | __author__ = "Philip Huppert"
17 | __copyright__ = "Copyright 2014, Philip Huppert"
18 | __license__ = "MIT"
19 |
20 |
21 | class RSAKey(common.AbstractWindowsCommand):
22 | """Extract base64/PEM encoded private RSA keys from physical memory."""
23 |
24 | def calculate(self):
25 | """Search for PEM encoded RSA keys."""
26 |
27 | # Load physical memory address space
28 | mem = utils.load_as(self._config, astype="physical")
29 |
30 | # Verify that the address space consists of one large block
31 | addrs = list(mem.get_available_addresses())
32 | assert len(addrs) == 1, "Physical memory is fragmented"
33 |
34 | # Determine size of memory
35 | mem_start, mem_size = addrs[0]
36 |
37 | # Read the physical memory in chunks
38 | for offset in xrange(0, mem_size, CHUNK_SIZE):
39 | chunk = mem.zread(offset, CHUNK_SIZE)
40 |
41 | # Search for private key markers in the current chunk
42 |
43 | # This might miss a key if it crosses a chunk boundary.
44 | # To keep the implementation simple, this issue is not
45 | # fixed (yet).
46 | if START_MARKER in chunk and END_MARKER in chunk:
47 | key = []
48 | in_key = False
49 |
50 | # Treat the chunk as a string and iterate over each
51 | # line to extract the key
52 | for line in chunk.splitlines():
53 | if START_MARKER in line and not in_key:
54 | in_key = True
55 | key.append(line)
56 | elif END_MARKER in line and in_key:
57 | in_key = False
58 | key.append(line)
59 | elif in_key:
60 | key.append(line)
61 |
62 | if len(key) != 0:
63 | yield "\n".join(key)
64 |
65 | def render_text(self, outfd, data):
66 | """Display found keys."""
67 |
68 | for key in data:
69 | outfd.writeln(key)
70 |
--------------------------------------------------------------------------------
/PhilipHuppert/vol-livemigration/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Philip Huppert
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/PhilipHuppert/vol-livemigration/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/PhilipHuppert/vol-livemigration/extract.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python2.7
2 | # coding=utf-8
3 |
4 | """Tool to extract VMotion live migration traffic from a packet capture."""
5 |
6 | import subprocess as sp
7 | import tempfile
8 | import sys
9 | import os
10 | import shutil
11 |
12 | __author__ = "Philip Huppert"
13 | __copyright__ = "Copyright 2015, Philip Huppert"
14 | __license__ = "MIT"
15 |
16 | TCPFLOW_PATH = "/usr/bin/tcpflow"
17 | VMOTION_MAGIC_A = "\0\0\0\0\x03\0\x05\0"
18 | VMOTION_MAGIC_A_OFFSET = 0
19 | VMOTION_MAGIC_B = "\x04\x0e\0\0"
20 | VMOTION_MAGIC_B_OFFSET = 0x55
21 |
22 |
23 | def tcpflow(*args):
24 | p = sp.Popen([TCPFLOW_PATH] + list(args), stdout=sp.PIPE, stderr=sp.PIPE)
25 | p.communicate()
26 | return p.returncode
27 |
28 |
29 | def copy_file(filename, ext, path):
30 | output = os.path.join(os.getcwd(), filename + ext)
31 | if not os.path.exists(output):
32 | print "Saving to %s" % output
33 | shutil.copy(path, output)
34 | else:
35 | print "Not overwriting %s" % output
36 |
37 |
38 | def check_magic(data, offset, magic):
39 | return data[offset:].startswith(magic)
40 |
41 |
42 | def main():
43 | # check for valid usage
44 | if len(sys.argv) != 2:
45 | sys.stderr.write("usage: %s pcap-file\n" % sys.argv[0])
46 | sys.exit(1)
47 |
48 | # verify that tcpflow is available
49 | if not os.path.isfile(TCPFLOW_PATH):
50 | sys.stderr.write("tcpflow not installed\n")
51 | sys.exit(1)
52 |
53 | # verify that input pcap is present
54 | pcap = sys.argv[1]
55 | if not os.path.isfile(pcap):
56 | sys.stderr.write("File not found: %s\n" % pcap)
57 | sys.exit(1)
58 |
59 | # create a temporary directory to hold data
60 | temp_dir = tempfile.mkdtemp(prefix="xtr")
61 |
62 | # extract all TCP streams from pcap
63 | if tcpflow("-r", pcap, "-o", temp_dir) != 0:
64 | sys.stderr.write("tcpflow error\n")
65 | sys.exit(1)
66 |
67 | # check each TCP stream for migration traffic
68 | for filename in os.listdir(temp_dir):
69 | print "Processing %s" % filename
70 | path = os.path.join(temp_dir, filename)
71 | with open(path, "r") as fp:
72 | header = fp.read(128)
73 |
74 | # check for VMotion magic bytes
75 | if check_magic(header, VMOTION_MAGIC_A_OFFSET, VMOTION_MAGIC_A) \
76 | and check_magic(header, VMOTION_MAGIC_B_OFFSET, VMOTION_MAGIC_B):
77 | print "Found VMotion migration in %s" % filename
78 | # copy file with VMotion TCP stream to working directory
79 | copy_file(filename, ".vmig", path)
80 |
81 | # remove temporary directory and contents
82 | shutil.rmtree(temp_dir)
83 |
84 |
85 | if __name__ == "__main__":
86 | main()
87 |
--------------------------------------------------------------------------------
/ProcessFuzzyHash/ProcessFuzzyHash/README.md:
--------------------------------------------------------------------------------
1 | # ProcessFuzzyHash Volatility Plugin
2 | Calculate and compare Windows processes fuzzy hashes. Created by Iñaki Abadía (2016/17)
3 |
4 | # Dependencies
5 |
6 | Run `installdeps.sh` to resolve both system and python dependencies.
7 |
8 |
--------------------------------------------------------------------------------
/ProcessFuzzyHash/ProcessFuzzyHash/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ProcessFuzzyHash/ProcessFuzzyHash/_exceptions.py:
--------------------------------------------------------------------------------
1 | # pylint: disable=E0401,C0111,C0103,C0412,E0602
2 | '''
3 | File name: _exceptions.py
4 | Author: Inaki Abadia
5 | Date created: 2/1/2017
6 | Date last modified: 9/11/2017
7 | Python Version: 2.7
8 | '''
9 |
10 | class InvalidAlgorithm(Exception):
11 | def __init__(self, msg):
12 | super(InvalidAlgorithm, self).__init__(msg)
13 | self.msg = msg
14 |
15 | def __str__(self):
16 | return repr("<" + self.msg + "> is not a valid Algorithm.")
17 |
18 | class NoPE(Exception):
19 | def __init__(self, msg):
20 | super(NoPE, self).__init__(msg)
21 | self.msg = msg
22 |
23 | def __str__(self):
24 | return repr("<" + self.msg + "> PDump doesn't contain a PE.")
25 |
26 | class NoSection(Exception):
27 | def __init__(self):
28 | super(NoSection, self).__init__()
29 |
30 | def __str__(self):
31 | return repr("Please specify at least one section (-h for help).")
32 |
33 | class InvalidPEHeader(Exception):
34 | def __init__(self, msg):
35 | super(InvalidPEHeader, self).__init__(msg)
36 | self.msg = msg
37 |
38 | def __str__(self):
39 | return repr("PE doesn't contain <" + self.msg + "> header.")
40 |
41 | class FullProcessAndPE(Exception):
42 | def __init__(self, msg):
43 | super(FullProcessAndPE, self).__init__(msg)
44 | self.msg = msg
45 |
46 | def __str__(self):
47 | return repr("Can't hash full process and PE/PE sections at the same time: {!s}".format(self.msg))
48 |
--------------------------------------------------------------------------------
/ProcessFuzzyHash/ProcessFuzzyHash/algorithms.py:
--------------------------------------------------------------------------------
1 | # pylint: disable=E0401,C0111,C0103,C0412,E0602
2 | '''
3 | File name: algorithms.py
4 | Author: Inaki Abadia
5 | Date created: 2/1/2017
6 | Date last modified: 9/11/2017
7 | Python Version: 2.7
8 | '''
9 |
10 | import ssdeep
11 | import fuzzyhashlib as fhash
12 | import tlsh
13 | import volatility.debug as debug
14 |
15 | import enumtypes as enum
16 | import _exceptions as exc
17 | import dcfldd
18 |
19 | ####################
20 | # ALGORITHM CONFIG #
21 | ####################
22 |
23 | # SUPERCLASS CONFIG
24 | class AlghConfig(object):
25 | """AlghConfig"""
26 |
27 | def __init__(self, alghorithm, alghType):
28 | self.algh = alghorithm
29 | self.alghtype = alghType
30 |
31 | # ALGORITHM TYPES CONFIG
32 | class BBRConfig(AlghConfig):
33 |
34 | def __init__(self, algorithm):
35 | super(BBRConfig, self).__init__(algorithm, enum.AlgorithmTypes.BBR)
36 |
37 | class BBHConfig(AlghConfig):
38 |
39 | def __init__(self, algorithm):
40 | super(BBHConfig, self).__init__(algorithm, enum.AlgorithmTypes.BBH)
41 |
42 | class SIFConfig(AlghConfig):
43 |
44 | def __init__(self, algorithm):
45 | super(SIFConfig, self).__init__(algorithm, enum.AlgorithmTypes.SIF)
46 |
47 | class LSHConfig(AlghConfig):
48 |
49 | def __init__(self, algorithm):
50 | super(LSHConfig, self).__init__(algorithm, enum.AlgorithmTypes.LSH)
51 |
52 | class CTPHConfig(AlghConfig):
53 |
54 | def __init__(self, algorithm):
55 | super(CTPHConfig, self).__init__(algorithm, enum.AlgorithmTypes.CTPH)
56 |
57 | # ALGORITHM CONFIG
58 | class SDHashConfig(SIFConfig):
59 |
60 | def __init__(self):
61 | super(SDHashConfig, self).__init__(enum.Algorithm.SDHash)
62 |
63 | class TLSHConfig(LSHConfig):
64 |
65 | def __init__(self):
66 | super(TLSHConfig, self).__init__(enum.Algorithm.TLSH)
67 |
68 | class SSDeepConfig(CTPHConfig):
69 |
70 | def __init__(self):
71 | super(SSDeepConfig, self).__init__(enum.Algorithm.SSDeep)
72 |
73 | class DcflddConfig(BBHConfig):
74 |
75 | def __init__(self):
76 | super(DcflddConfig, self).__init__(enum.Algorithm.dcfldd)
77 |
78 | def get_alghconfig_instance(algh):
79 | if algh == enum.Algorithm.SDHash:
80 | return SDHashConfig()
81 | elif algh == enum.Algorithm.TLSH:
82 | return TLSHConfig()
83 | elif algh == enum.Algorithm.SSDeep:
84 | return SSDeepConfig()
85 | elif algh == enum.Algorithm.dcfldd:
86 | return DcflddConfig()
87 | else:
88 | raise exc.InvalidAlgorithm(algh)
89 |
90 | ##############
91 | # ALGORITHMS #
92 | ##############
93 |
94 | # Algorithm superclass
95 | class HashAlgorithm(object):
96 |
97 | @staticmethod
98 | def hash(data, alghConfig):
99 | raise InvalidAlgorithm(__name__)
100 |
101 | # Algorithm types
102 | class BBRAlgorithm(HashAlgorithm):
103 |
104 | def hash(self, data, alghConfig):
105 | super(BBRAlgorithm, self).__init__(data, alghConfig)
106 |
107 | class BBHAlgorithm(HashAlgorithm):
108 |
109 | def hash(self, data, alghConfig):
110 | super(BBHAlgorithm, self).__init__(data, alghConfig)
111 |
112 | class SIFAlgorithm(HashAlgorithm):
113 |
114 | def hash(self, data, alghConfig):
115 | super(SIFAlgorithm, self).__init__(data, alghConfig)
116 |
117 | class LSHAlgorithm(HashAlgorithm):
118 |
119 | def hash(self, data, alghConfig):
120 | super(LSHAlgorithm, self).__init__(data, alghConfig)
121 |
122 | class CTPHAlgorithm(HashAlgorithm):
123 |
124 | def hash(self, data, alghConfig):
125 | super(CTPHAlgorithm, self).__init__(data, alghConfig)
126 |
127 | # Algorithms
128 | class SDHashAlgorithm(SIFAlgorithm):
129 |
130 | def hash(self, data, alghConfig):
131 | try:
132 | retdata = fhash.sdhash(data).hexdigest()
133 | except ValueError:
134 | retdata = '-'
135 | debug.warning("SDHash needs an input of at least 512 bytes. Too short: {!s}".format(len(data)))
136 | return retdata
137 |
138 | def compare(self, h1, h2):
139 | return fhash.sdhash(hash=h1)-fhash.sdhash(hash=h2)
140 |
141 | class TLSHAlgorithm(LSHAlgorithm):
142 |
143 | def hash(self, data, alghConfig):
144 | retdata = tlsh.hash(data)
145 | if not retdata:
146 | debug.warning("TLSH generated empty hash")
147 | retdata = '-'
148 | return retdata
149 |
150 | def compare(self, h1, h2):
151 | return tlsh.diffxlen(h1, h2)
152 |
153 | class SSDeepAlgorithm(CTPHAlgorithm):
154 |
155 | def hash(self, data, alghConfig):
156 | return ssdeep.hash(data)
157 |
158 | def compare(self, h1, h2):
159 | return ssdeep.compare(str(h1), str(h2))
160 |
161 | class DcflddAlgorithm(BBHAlgorithm):
162 |
163 | def hash(self, data, alghConfig):
164 | return dcfldd.hash(data, 100, dcfldd.MD5)
165 |
166 | def compare(self, h1, h2):
167 | return dcfldd.compare(str(h1), str(h2))
168 |
169 | def get_algh_instance(algh):
170 | if algh == enum.Algorithm.SDHash:
171 | return SDHashAlgorithm()
172 | elif algh == enum.Algorithm.TLSH:
173 | return TLSHAlgorithm()
174 | elif algh == enum.Algorithm.SSDeep:
175 | return SSDeepAlgorithm()
176 | elif algh == enum.Algorithm.dcfldd:
177 | return DcflddAlgorithm()
178 | else:
179 | raise exc.InvalidAlgorithm(algh)
180 |
--------------------------------------------------------------------------------
/ProcessFuzzyHash/ProcessFuzzyHash/dcfldd.py:
--------------------------------------------------------------------------------
1 | # pylint: disable=E0401,C0111,C0103,C0412,E0602
2 | '''
3 | File name: dcfldd.py
4 | Author: Inaki Abadia
5 | Date created: 2/1/2017
6 | Date last modified: 9/4/2017
7 | Python Version: 2.7
8 | '''
9 |
10 | from __future__ import division
11 | import hashlib
12 | import math
13 |
14 | MD5, SHA1, SHA256, CTPH = range(4)
15 |
16 | class InvalidDcflddHashFunc(Exception):
17 | def __init__(self, msg):
18 | super(InvalidDcflddHashFunc, self).__init__(msg)
19 | self.msg = msg
20 |
21 | def __str__(self):
22 | return repr("<" + self.msg + "> is not a valid dcfldd hash function.")
23 |
24 | class InvalidDcflddComparison(Exception):
25 | def __init__(self, msg):
26 | super(InvalidDcflddComparison, self).__init__(msg)
27 | self.msg = msg
28 |
29 | def __str__(self):
30 | return repr("Can't compare different hash functions: <" + self.msg + ">.")
31 |
32 |
33 | def hash(data, blocks, hash_f):
34 | dcfldd_hash = ''
35 | # Data length
36 | bs = math.ceil(len(data) / blocks)
37 | bs = int(bs)
38 |
39 | # hash function
40 | if hash_f == MD5:
41 | hash_func = hashlib.md5
42 | dcfldd_hash = 'md5:'
43 | elif hash_f == SHA1:
44 | hash_func = hashlib.sha1
45 | dcfldd_hash = 'sha1:'
46 | elif hash_f == SHA256:
47 | hash_func = hashlib.sha256
48 | dcfldd_hash = 'sha256:'
49 | else:
50 | raise InvalidDcflddHashFunc(hash)
51 |
52 | # hash
53 | hash_array = [hash_func(data[i:i+bs]).hexdigest() for i in range(0, len(data), bs)]
54 | # Build hash str
55 | for h in hash_array:
56 | dcfldd_hash += h + ':'
57 | return dcfldd_hash[:-1]
58 |
59 | def compare(h1, h2):
60 | score = 0
61 | h1_array = h1.split(':')
62 | h2_array = h2.split(':')
63 |
64 | if not h1_array[0] == h2_array[0]:
65 | raise InvalidDcflddComparison(h1_array[0] + ' + ' + h2_array[0])
66 |
67 | for i in range(1, len(h1_array)):
68 | if h1_array[i] == h2_array[i]:
69 | score = score + 1
70 | return score
71 |
--------------------------------------------------------------------------------
/ProcessFuzzyHash/ProcessFuzzyHash/enumtypes.py:
--------------------------------------------------------------------------------
1 | # pylint: disable=E0401,C0111,C0103,C0412,E0602
2 | '''
3 | File name: enumtypes.py
4 | Author: Inaki Abadia
5 | Date created: 2/1/2017
6 | Date last modified: 9/11/2017
7 | Python Version: 2.7
8 | '''
9 |
10 | import _exceptions as exc
11 |
12 | class Algorithm(object):
13 | SDHash, TLSH, SSDeep, dcfldd = range(4)
14 | def name(self, algh):
15 | if algh == self.SDHash:
16 | return 'SDHash'
17 | elif algh == self.TLSH:
18 | return 'TLSH'
19 | elif algh == self.SSDeep:
20 | return 'SSDeep'
21 | elif algh == self.dcfldd:
22 | return 'dcfldd'
23 | else:
24 | raise exc.InvalidAlgorithm(algh)
25 |
26 | def resolve(self, algh):
27 | if algh.lower() == "sdhash":
28 | return self.SDHash
29 | elif algh.lower() == "tlsh":
30 | return self.TLSH
31 | elif algh.lower() == "ssdeep":
32 | return self.SSDeep
33 | elif algh.lower() == "dcfldd":
34 | return self.dcfldd
35 | else:
36 | raise exc.InvalidAlgorithm(algh)
37 |
38 | class AlgorithmTypes(object):
39 | BBR, BBH, SIF, LSH, CTPH = range(5)
40 |
--------------------------------------------------------------------------------
/ProcessFuzzyHash/ProcessFuzzyHash/installdeps.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Dependencies
4 | systemdeps="python2.7 python-dev python-pip ssdeep libfuzzy-dev git cmake"
5 | pythondeps="pycrypto distorm3 pefile ssdeep fuzzyhashlib"
6 |
7 | # Install system dependencies
8 | apt-get install -y $systemdeps
9 |
10 | # Install python dependencies
11 | pip install $pythondeps
12 |
13 | # Install TLSH
14 | git clone "https://github.com/trendmicro/tlsh.git" /tmp/tlsh/
15 | oldpwd=$(pwd)
16 | cd /tmp/tlsh/
17 | ./make.sh
18 | cd py_ext
19 | python setup.py build
20 | python setup.py install
21 | cd $oldpwd
22 | rm -rf /tmp/tlsh/
--------------------------------------------------------------------------------
/ProcessFuzzyHash/README.md:
--------------------------------------------------------------------------------
1 | Author: Iñaki Abadía and Ricardo J. Rodríguez
2 |
--------------------------------------------------------------------------------
/ProcessFuzzyHash/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ProcessFuzzyHash/processfuzzyhash.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/ProcessFuzzyHash/processfuzzyhash.pdf
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | community
2 | =========
3 |
4 | Volatility plugins developed and maintained by the community. See the README file inside each author's subdirectory for a link to their respective GitHub profile page where you can find usage instructions, dependencies, license information, and future updates for the plugins.
5 |
6 | usage
7 | =========
8 |
9 | 1. Git clone the [Volatility](https://github.com/volatilityfoundation/volatility) repository or [Download a Release](http://www.volatilityfoundation.org/#!releases/component_71401)
10 | 2. Git clone this repository to $PLUGINSPATH
11 | 3. Pass the --plugins=$PLUGINSPATH option to Volatility when you run it (see [Specifying Additional Plugin Directories](https://github.com/volatilityfoundation/volatility/wiki/Volatility%20Usage#specifying-additional-plugin-directories))
12 |
13 | NOTE: If you pass the root of the $PLUGINSPATH directory, then all plugins will recursively be loaded. Its possible that plugins may try to register the same command line options and produce a conflict. If this happens, just point --plugins at one or more specific subdirectories (`:` separated on Linux/Mac or `;` separated on Windows).
14 |
15 | disclaimer
16 | =========
17 | These plugins are written by various authors and collected from the authors' GitHub repositories, websites and blogs at a particular point in time. We don't guarantee that the plugins you download from this repo will be the most recent ones published by the individual authors, that they're compatible with the most recent version of Volatility, or that they report results accurately.
18 |
19 | contributing
20 | =========
21 |
22 | The best way to contribute is to fork the repository, add or modify plugins, and then submit a pull request.
23 |
24 | frameworks
25 | =========
26 |
27 | Researchers and developers in the community have also created frameworks that build on top of Volatility. These aren't necessarily Volatility plugins (that you would import with --plugins) and usually they contain additional modules, configurations, and components. For that reason, we don't feature those frameworks in this repository, but we'd still like to reference them:
28 |
29 | * [Autopsy Plugins](https://github.com/markmckinnon/Autopsy-Plugins/tree/master/Volatility) by Mark McKinnon
30 | * [PyREBox](https://github.com/Cisco-Talos/pyrebox) by Xabier Ugarte-Pedrero at Cisco Talos
31 | * [Cuckoo Sandbox](https://github.com/cuckoobox/cuckoo) uses Volatility for its Memory module
32 | * [VolDiff](https://github.com/aim4r/VolDiff) Malware Memory Footprint Analysis by @aim4r
33 | * [Evolve](https://github.com/JamesHabben/evolve) Web interface for the Volatility Memory Forensics Framework by James Habben
34 | * [GVol](https://github.com/eg-cert/GVol) Lightweight GUI (Java) by EG-CERT
35 | * [LibVMI](https://github.com/libvmi/libvmi) Simplified Virtual Machine Introspection
36 | * [DAMM](https://github.com/504ensicsLabs/DAMM) Differencial Analysis of Malware in Memory
37 | * [YaraVol](https://bitbucket.org/Ft44k/yavol/) GUI for Volatility Framework and Yara
38 | * [VolUtility](https://github.com/kevthehermit/VolUtility) Web Interface for Volatility by Kevin Breen
39 | * [ROPMEMU](https://github.com/vrtadmin/ROPMEMU) A framework to analyze, dissect and decompile complex code-reuse attacks by Mariano Graziano
40 | * [VolatilityBot](https://github.com/mkorman90/VolatilityBot) An automated memory analyzer for malware samples and memory dumps by Martin Korman
41 | * [ProfileScan](https://github.com/P1kachu/VolatilityProfileScan) Profile detection for Volatility by Stanislas Lejay (P1kachu)
42 |
43 | Don't see your project here? Let us know by submitting a pull request, creating an issue, or tweet us at @volatility.
44 |
--------------------------------------------------------------------------------
/RopFind/README.md:
--------------------------------------------------------------------------------
1 | Author: Or Chechik and Inon Weber
2 |
3 | See https://github.com/orchechik/ropfind for updates and licensing information.
--------------------------------------------------------------------------------
/ShachafAtun/README.md:
--------------------------------------------------------------------------------
1 | Author: Shachaf Atun
2 |
3 | See https://github.com/kslgroup/WinObj and https://github.com/kslgroup/TokenImp-Token_Impersonation_Detection for updates and license information.
--------------------------------------------------------------------------------
/Shemulator/README.md:
--------------------------------------------------------------------------------
1 | # shemu (SHell + EMULATOR)
2 | -(non-Volatility) Requirements:
3 |
4 | 1) Unicorn (https://github.com/unicorn-engine/unicorn ) must be installed.
5 | 2) Capstone (https://github.com/aquynh/capstone) must be installed.
6 |
7 | - What are these files?
8 |
9 | shemulator.py is a (very slightly) modified version of volshell. All that was added was a function (emu()) which calls into shemulator_api.py. shemulator_api contains a python class to handle creating a unicorn instance and letting the user interact with it as they want.
10 |
11 | - How do I set this up?
12 |
13 | Once you've installed unicorn and capstone, move volshell.py out of the plugins directory. Then add in shemulator_api.py and shemulator.py, but rename shemulator.py 'volshell.py' (We're sorry.)
14 |
15 | - Why the whole song and dance with volshell?
16 |
17 | We wanted to extend the functionality of volshell, not replace any of it, so we thought the best way to go about this was simply editing the existing plugin. Unfortunately, this means having to replace volshell to not run into issues with certain classes already being defined (if both shemulator and volshell are in the plugins directory) or with things depending on volshell not being able to access it (if we remove volshell but don't rename shemulator). (We're still sorry)
18 |
19 | - What does all of this actually do?
20 |
21 | shemu extends volshell to include some debugger-like functionality that (to the best of our knowledge) was not present before. By calling the emu() function, the user can begin emulating code at a specified address.
22 |
23 | There are options to:
24 |
25 | *set breakpoints at certain addresses,
26 |
27 | *step through the emulation instruction by instruction,
28 |
29 | *set and read register values,
30 |
31 | *collect the starting addresses of new basic blocks being visited, and
32 |
33 | *dump the emulated code into text files
34 |
35 | All of this should make using volatility to analyze code a much more pleasant task, alleviating the need to dump process memory and throw it into IDA to do any sort of dynamic analysis (though that is still probably prefferable for more intensive tasks).
36 |
37 | - How do I run your code?
38 |
39 | Once you run volshell, you simply run the 'emu()' command with whatever options you want. The anatomy of emu() is:
40 |
41 | emu( address = integer, step = 1 or 0, max_inst = integer, dis_mode = 64 if 64 bit, otherwise ignore, print_regs = ['register1', 'register2', ...], stuff = {'register':integer, 'register2':integer, ...}, inst_dump = 1 or 0, dump_blocks = 1 or 0, v = 1 or 0, patch = {integer:'\xCO\xDE',...}, brk = [integer, integer, ....], dump_dir = 'some_directory')
42 |
43 | address is the address at which to start the emulation. No default.
44 |
45 | step controls if you are stepping through the emulation (and given control to issue a set of commands after each instruction). Default 0.
46 |
47 | max_inst gives the maximum number of instructions to execute. Default 100.
48 |
49 | dis_mode tells shemulator to be in 64 bit or 32 bit mode. Default 32.
50 |
51 | print_regs is a list of registers you want to print out throughout the program. Default ['eax', 'ebx', 'ecx', 'edx'].
52 |
53 | stuff is a dictionary of 'register':value pairs, where each register is initialized with the corresponding value. Default {}
54 |
55 | inst_dump controls if, when printing registers, to do so after each instruction (if inst_dump is 1) or at the end of each basic block (if 0). Default 0.
56 |
57 | dump_blocks controls if shemulator prints the starting addresses of each basic block visited during emulation, after emulation is finished. Default 0.
58 |
59 | v controls verbosity, i.e. if the instructions are printed as emulation happens (if 1) or not (if 0). Default 1.
60 |
61 | patch is a dictionary of address:'\xCO\xDE' pairs, where, when the listed addresses are mapped into memory, the true values are overwritted with the supplied code. Default {}.
62 |
63 | brk is a list of addresses to set breakpoints on. Default []
64 |
65 | dump_dir controls if you want to dump all the emulated code into whatever supplied directory. Default is '', creating no directory and dumping no code.
66 |
67 | - How do I know it works?
68 | We've created two memory images (64 and 32 bit windows 10) running a dummy program we wrote. Here are links to the program, the ida.db, and the memory images: TODO
69 |
70 | In the 64 bit system, the PID is 2928 and the body of the program starts at TODO
71 |
72 | In the 32 bit system, the PID is 9632 and the body starts at 0x3724a0. In this case, to begin emulation from inside volshel (and the correct context), type:
73 |
74 | emu(0x3724a0)
75 |
76 | with whatever options you want.
77 |
78 | - Who worked on this (Alphabetically)?
79 |
80 | Sweta Ghimire, Ryan Maggio, Raphaela Mettig of the Louisiana State University Cybersecurity Lab
81 |
--------------------------------------------------------------------------------
/ShimcacheMemory/README.md:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------------------
2 | Submitters
3 | --------------------------------------------------------------------------------
4 | Author(s): Fred House (Mandiant, a FireEye Company) - Twitter: @0xF2EDCA5A
5 | Andrew Davis (Mandiant, a FireEye Company)
6 | Claudiu Teodorescu (Mandiant, a FireEye Company) - Twitter: @cteo13
7 |
8 | Date: 2015-09-29
9 |
10 | Description:
11 | Parses the Windows Application Compatibility Database (aka, ShimCache) from
12 | the module or process memory that contain the database.
13 |
14 | --------------------------------------------------------------------------------
15 | How to use
16 | --------------------------------------------------------------------------------
17 | 1) Capture system memory
18 |
19 | NOTE: During testing of this plugin on Windows XP, at least one tool
20 | (specifically, DumpIt.exe) did not correctly dump the process memory
21 | for winlogon.exe. As a result, the shim cache in memory could not be
22 | parsed. A memory image of the same system taken with FTK Imager parsed
23 | without issue.
24 |
25 | 2) Run the "shimcachemem" plugin. The following command writes the shim cache
26 | contents to standard output:
27 |
28 | ```> python vol.py -f Win2012R2x64.raw --profile=Win2012R2x64 --kdbg=0xf801a185b9b0 shimcachemem```
29 |
30 | The following command writes the output to a CSV file:
31 |
32 | ```> python vol.py -f Win2012R2x64.raw --profile=Win2012R2x64 --kdbg=0xf801a185b9b0 shimcachemem --output=csv --output-file=Win2012R2x64.csv```
33 |
34 | 3) In addition to the output format, the plugin supports the following options:
35 |
36 | ```
37 | ---------------------------------------------------------------------------
38 | | -c | --clean_file_paths | Strips UNC path prefixes ("\\??\") and replaces |
39 | | | | SYSVOL with "C:". Intended an a convenience for |
40 | | | | analysts. |
41 | | | | |
42 | | -P | --print_offset | Prints the virtual and physical offset of each |
43 | | | | shim cache entry. Intended to facilitate |
44 | | | | additional forensic analysis of the memory |
45 | | | | image. |
46 | | | | |
47 | | -i | --ignore_win_apps | On Windows 10, the shim cache contains entries |
48 | | | | for Windows apps, which are in a format that is |
49 | | | | not parsed by this plugin. This option excludes |
50 | | | | these entries from the output. |
51 | | | | |
52 | | | --system_name | An optional system name to add as a column to |
53 | | | | the output. |
54 | | | | |
55 | ---------------------------------------------------------------------------
56 | ```
57 |
58 | --------------------------------------------------------------------------------
59 | Motivation
60 | --------------------------------------------------------------------------------
61 | Shim cache is a highly valuable forensic artifact used to identify evidence of
62 | file execution. In addition to recording potential file executions, the cache is
63 | ordered, meaning that an analyst can identify other files that may have executed
64 | before or after a file of interest.
65 |
66 | Most forensic tools that parse the shim cache rely on the cache stored in the
67 | Windows registry. The cache in the registry is only updated when a system is
68 | shutdown so this approach has the disadvantage of only parsing cache entries
69 | since the last shutdown. On systems that are not rebooted regularly (e.g.,
70 | production servers) an analyst must either use out-of-date shim cache data or
71 | request a system reboot.
72 |
73 | This plugin parses the shim cache directly from the module or process containing
74 | the cache, thereby providing analysts access to the most up-to-date cache. The
75 | plugin supports Windows XP SP2 through Windows 10 on both 32 and 64
76 | bit architectures.
77 |
--------------------------------------------------------------------------------
/ShimcacheMemory/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ShuseiTomonaga/README.md:
--------------------------------------------------------------------------------
1 | Author: Shusei Tomonaga
2 |
3 | See https://github.com/JPCERTCC/MalConfScan for updates and license information.
--------------------------------------------------------------------------------
/SlaviParpulev/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/SlaviParpulev/__init__.py
--------------------------------------------------------------------------------
/SlaviParpulev/psempire.py:
--------------------------------------------------------------------------------
1 | """
2 | @author: Slavi Parpulev
3 | """
4 | import re
5 | import base64
6 | import volatility.plugins.common as common
7 | import volatility.utils as utils
8 | import volatility.win32.tasks as tasks
9 | import volatility.plugins.malware.malfind as malfind
10 | import volatility.plugins.taskmods as taskmods
11 |
12 | try:
13 | import yara
14 | has_yara = True
15 | except ImportError:
16 | has_yara = False
17 |
18 | signatures = {
19 | 'namespace1' : 'rule pivars {strings: $command = { \
20 | 70 6f 77 65 72 73 68 65 6c 6c 2e 65 78 65 20 2d\
21 | 4e 6f 50 20 2d 4e 6f 6e 49 20 2d 57 20 48 69 64\
22 | 64 65 6e 20 2d 45 6e 63 20}\
23 | condition: $command}'
24 | }
25 |
26 | # signatures = {
27 | # 'namespace1' : 'rule pivars {strings: $a = /powershell.exe.-NoP.-NonI.-W.Hidden.-Enc.([a-zA-Z0-9]+)/ condition: $a}'
28 | # }
29 |
30 |
31 | class PSEmpire(taskmods.DllList):
32 | """A plugin detecting the presence of PowerShell Empire. Idally run against a PID of powershell.exe"""
33 |
34 |
35 | def get_vad_base(self, task, address):
36 | """ Get the VAD starting address """
37 |
38 | for vad in task.VadRoot.traverse():
39 | if address >= vad.Start and address < vad.End:
40 | return vad.Start
41 |
42 | # This should never really happen
43 | return None
44 |
45 | def calculate(self):
46 | if not has_yara:
47 | debug.error("Yara must be installed for this plugin")
48 |
49 | addr_space = utils.load_as(self._config)
50 |
51 | if not self.is_valid_profile(addr_space.profile):
52 | debug.error("This command does not support the selected profile.")
53 | # For each process in the list
54 | for task in self.filter_tasks(tasks.pslist(addr_space)):
55 | # print task.ImageFileName
56 | for vad, address_space in task.get_vads(vad_filter = task._injection_filter):
57 | # Injected code detected if there's values returned
58 | rules = yara.compile(sources = signatures)
59 | scanner = malfind.VadYaraScanner(task = task, rules = rules)
60 | # print 'before'
61 | for hit, address in scanner.scan():
62 | vad_base_addr = self.get_vad_base(task, address)
63 |
64 | # Get a chuck of memory of size 2048 next to where the string was detected
65 | content = address_space.zread(address, 2048)
66 | yield task, address, vad_base_addr, content
67 | break
68 | # break # Show only 1 instance of detected injection per process
69 |
70 | def render_text(self, outfd, data):
71 | for task, address, vad_base_addr, content in data:
72 | finalstring = []
73 | # hex dump returns 16 bytes at a time, walk the entire dump and get all values in finalstring
74 | for offset,h,c in utils.Hexdump(content):
75 | finalstring.append(''.join(c))
76 | # Get only the base64 part of the string and decode utf16 otherwise next regex fails to interpret the value as ascii
77 | obfuscated = base64.b64decode(re.findall(r'.+-Enc\.([a-zA-Z0-9]+)', "".join(finalstring))[0]).decode('utf16')
78 | # Get server value and port from the string
79 | try:
80 | server = re.findall(r'http.+//(.+):', obfuscated)[0]
81 | except:
82 | server = "Not detected"
83 | try:
84 | port = re.findall(r'http.+:(.+)/', obfuscated)[0]
85 | except:
86 | port = "Not found"
87 |
88 | outfd.write("Process: {0} Pid: {1} Vad_base: {2:#x} Detected at Address: {3:#x}\n".format(
89 | task.ImageFileName, task.UniqueProcessId, vad_base_addr, address))
90 |
91 | outfd.write("Connecting to - Server: {0} Port: {1}\n".format(
92 | server, port))
93 |
94 | outfd.write("{0}\n".format("\n".join(
95 | ["{0:#010x} {1:<48} {2}".format(address + o, h, ''.join(c))
96 | for o, h, c in utils.Hexdump(content[:64])
97 | ])))
98 |
--------------------------------------------------------------------------------
/StanislasLejay/README.md:
--------------------------------------------------------------------------------
1 | Author: Stanislas Lejay
2 |
3 | See https://github.com/P1kachu/VolatilityProfileScan for updates and license information.
4 |
5 |
--------------------------------------------------------------------------------
/StanislasLejay/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/StanislasLejay/linux/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/StanislasLejay/linux/__init__.py
--------------------------------------------------------------------------------
/StanislasLejay/linux/get_profile.py:
--------------------------------------------------------------------------------
1 | # Volatility linux_get_profile plugin
2 | # Copyright (c) 2016 Stanislas 'P1kachu' Lejay (p1kachu@lse.epita.fr)
3 | #
4 | # Donated under Volatility Foundation, Inc. Individual Contributor Licensing
5 | # Agreement
6 | #
7 | # This plugin is free software; you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation; either version 2 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This plugin is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this plugin. If not, see .
19 |
20 | """
21 | @author : Stanislas Lejay
22 | @license : GPL 2 or later
23 | @contact : p1kachu@lse.epita.fr
24 | """
25 |
26 | import re
27 | import volatility.scan as scan
28 | import volatility.utils as utils
29 | import volatility.commands as commands
30 |
31 | READ_SIZE = 0x100
32 |
33 |
34 | class LinuxVersionScanner(scan.BaseScanner):
35 | checks = []
36 |
37 | def __init__(self, signatures=None):
38 | scan.BaseScanner.__init__(self)
39 | self.checks = [("VersionCheck", {'signatures': signatures})]
40 |
41 |
42 | class VersionCheck(scan.ScannerCheck):
43 | """ Looks for linux kernel string """
44 |
45 | def __init__(self, address_space, signatures=None):
46 | scan.ScannerCheck.__init__(self, address_space)
47 |
48 | def check(self, offst):
49 | dump_chunk = self.address_space.read(offst, READ_SIZE)
50 |
51 | # If linux not in the chunk, skip it completely
52 | if "Linux" not in dump_chunk:
53 | self.skip(None, None)
54 | else:
55 | # Else, return the correct string, maybe with junk after
56 | # but we don't care
57 | found = re.search('Linux version [\w\.-]* .*', dump_chunk)
58 |
59 | if found is not None:
60 | return True
61 |
62 | return False
63 |
64 | def skip(self, data, off):
65 | return READ_SIZE
66 |
67 |
68 | class LinuxGetProfile(commands.Command):
69 | """
70 | Scan to try to determine the Linux profile
71 | """
72 |
73 | distribution_profiles = {
74 | 'centos': 'CentOS',
75 | 'cent os': 'CentOS',
76 | 'debian': 'Debian',
77 | 'fedora': 'Fedora',
78 | 'opensuse': 'OpenSUSE',
79 | 'open suse': 'OpenSUSE',
80 | 'redhat': 'Red Hat',
81 | 'red hat': 'Red Hat',
82 | 'ubuntu': 'Ubuntu',
83 | '': 'Distribution Not found'
84 | }
85 |
86 | def calculate(self):
87 | address_space = utils.load_as(self._config, astype='physical')
88 |
89 | scanner = LinuxVersionScanner()
90 |
91 | for offst in scanner.scan(address_space):
92 |
93 | # Read the full size, like before
94 | magic_string = address_space.zread(offst, READ_SIZE)
95 |
96 | if self._config.get_value('verbose') != 0:
97 | s = '[ ] DEBUG: String found {0} at offset {1}'
98 | print(s.format(magic_string.replace('\n', ''), hex(offst)))
99 |
100 | # And directly return the string (there shouldn't
101 | # be more than one string matching the regex
102 | return magic_string
103 |
104 | def render_text(self, outfd, data):
105 | if data is None:
106 | outfd.write("Couldn't determine OS")
107 | return
108 |
109 | # Find and remove everything before the kernel version
110 | beg_string = "Linux version"
111 | pos = data.find(beg_string) + len(beg_string) + 1
112 | data = data[pos:]
113 |
114 | k_version = re.search("[\w\.-]*", data).group()
115 | cmpile_by = re.search("\([\w@\.-]*\)", data).group()
116 | cmpiler = re.search("\([\w\s\.-]*\(.*\).*\)", data).group()
117 |
118 | outfd.write("Informations found:\n")
119 | outfd.write(" Kernel version: {0}\n".format(k_version))
120 | outfd.write(" Compiled by : {0}\n".format(cmpile_by))
121 | outfd.write(" Compiler : {0}\n".format(cmpiler))
122 |
123 | for distrib in self.distribution_profiles:
124 | if distrib in cmpiler.lower():
125 | outfd.write('Profile: {0} ({1})\n'.format(self.distribution_profiles[distrib], k_version))
126 | break
127 | outfd.flush()
128 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/10d8f887-b625-426f-b134-8147a780c369_UAC_sdb.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | UAC pop-up bypass (COM)
5 | push 10840014h ; (FOF_NOCONFIRMATION|FOF_SILENT|FOFX_SHOWELEVATIONPROMPT|FOFX_NOCOPYHOOKS|FOFX_REQUIREELEVATION|FOF_NOERRORUI)
6 | Takahiro Haruyama
7 | 2015-02-26T06:10:23
8 |
9 |
10 |
11 |
12 |
13 | \x68\x14\x00\x84\x10
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/26f643d6-6af9-4691-bfc3-f1823d4e9047_code_injection_hook.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | process code injection (based on unknown hook)
5 |
6 | Takahiro Haruyama
7 | 2015-02-26T03:23:58
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | true
16 |
17 |
18 |
19 | unknown
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/2823537b-8c9a-454a-8bf4-3aa5ef76ec54_information-stealing_malware.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Information-Stealing Malware
5 | Information-Stealing Malware (e.g., ZeuS, SpyEye, Citadel, Andromeda).
6 | Takahiro Haruyama
7 | 2014-09-01T08:21:19
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | HttpSendRequestA
16 |
17 |
18 |
19 | HttpSendRequestW
20 |
21 |
22 |
23 | HttpSendRequestExA
24 |
25 |
26 |
27 | HttpSendRequestExW
28 |
29 | unknown
30 |
31 |
32 | 4040404020
33 |
34 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/2b5527f3-e5c4-4f0b-b9fc-bcd2221c313c_PIC_PEB.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | position independent code (PEB)
5 | This indicator focuses on 32-bit malware only
6 | Takahiro Haruyama
7 | 2014-11-21T10:12:37
8 |
9 |
10 |
11 |
12 |
13 | \x64\xA1\x30\x00\x00\x00\x8B\x40\x0C
14 |
15 |
16 |
17 | \x64\x8B.\x30\x8B.\x0C\x8B
18 |
19 |
20 |
21 | getting PEB #1PEB#2PEB#1getPCror13AddHash32rol13AddHash32poisonIvyHashrol7AddHash32rol5AddHash32rol3XorEaxrol3XorEax2ror7AddHash32ror9AddHash32ror11AddHash32ror13AddHash32Sub1shl7shr19Hash32sll1AddHash32msfHash32
22 |
23 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/840ae4e7-41eb-4132-a5fe-48c910d99b96_ntfsEA_driver.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | using NTFS $EA (driver)
5 |
6 | Takahiro Haruyama
7 | 2014-11-28T06:00:36
8 |
9 |
10 |
11 |
12 |
13 |
14 | QueryEaFile
15 |
16 |
17 |
18 | SetEaFile
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/a50223b5-b213-43e9-beac-dfe9c1ca240c_rogue_svchost.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | rogue svchost
5 | 2014-08-06T02:11:39Z
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | services.exe
14 |
15 |
16 |
17 | svchost.exe
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/b28d0314-ca44-45da-97e6-be540a92d929_hollowing.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Process/module hollowing
5 | Check with ldrmodules for empty paths.
6 | Francesco "dfirfpi" Picasso
7 | 2015-02-26T14:04:20
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/b61f88d5-9453-469b-94cd-c5ef59c972db_ntfsEA_proc.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | using NTFS $EA (process)
5 |
6 | Takahiro Haruyama
7 | 2014-11-28T05:58:45
8 |
9 |
10 |
11 |
12 |
13 |
14 | QueryEaFile
15 |
16 |
17 |
18 | SetEaFile
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/c02075e0-c6a4-4f4b-9ad1-0a8ca9232db3_inline_api_hooks_uknown.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Inline API hook uknown module
5 | Inline API hooking with hooks inside <unknown> modules
6 | Francesco "dfirfpi" Picasso
7 | 2015-02-13T13:45:09
8 |
9 |
10 |
11 | <unknown>
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/c7121f8f-8401-4f92-bb02-2be6bb48c3b4_code_injection_pattern.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | process code injection (based on hex pattern)
5 |
6 | Takahiro Haruyama
7 | 2015-02-26T03:46:35
8 |
9 |
10 |
11 |
12 |
13 |
14 | \x64\xA1\x30\x00\x00\x00\x8B\x40\x0C
15 |
16 |
17 |
18 | \x64\x8B.\x30\x8B.\x0C\x8B
19 |
20 |
21 |
22 | \xE8\x00\x00\x00\x00[\x5D\x5E\x58]
23 |
24 |
25 |
26 | \x4d\x5a
27 |
28 |
29 |
30 | \x50\x45
31 |
32 |
33 |
34 | \xff[\x56\x96]
35 |
36 |
37 |
38 |
39 |
40 | MZ signature
41 |
42 |
43 | PIC code (call [ESI+?])
44 |
45 | PIC code(PEB#1)PIC code(PEB#2)PIC code(getPC)PE signature
46 |
47 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/cdcd5fdb-fcd3-4947-8c76-d2fbdc1b5f82_UAC_COM.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | UAC pop-up bypass (sdb)
5 | http://blog.jpcert.or.jp/2015/02/a-new-uac-bypass-method-that-dridex-uses.html
6 |
7 |
8 | Takahiro Haruyama
9 | 2014-06-10T06:32:32
10 |
11 |
12 |
13 |
14 | AllocateAndInitializeSidEqualSidRtlQueryElevationFlagsGetTokenInformationGetSidSubAuthorityGetSidSubAuthorityCountsdbinst.exeRedirectEXEsmss.exe
15 |
16 | 151515151515202015on
17 |
18 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/e2bd07db-dbfd-45f8-a81d-24314516d0c6_equation_driver_generic.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | EquationDrug HDD/SSD firmware operation (kernel,generic)
5 | nls_933w.dll/win32m.sys
6 | https://securelist.com/blog/research/69203/inside-the-equationdrug-espionage-platform/
7 | Takahiro Haruyama
8 | 2015-05-07T10:20:58
9 |
10 |
11 |
12 |
13 | WRITE_PORT_ULONGWRITE_PORT_USHORTWRITE_PORT_BUFFER_USHORTWRITE_PORT_UCHARWRITE_REGISTER_UCHARWRITE_REGISTER_BUFFER_USHORTWRITE_REGISTER_ULONGWRITE_REGISTER_USHORTPsCreateSystemThreadKeInsertQueueDpcKeRaiseIrqlToDpcLeveltrue
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/e5f73cf8-55ed-463f-81ec-70ffaf81ade9_lsass_checks.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | LSASS check
5 | [v] ImagePath: %SystemRoot%\System32\lsass.exe (defaulting %SystemRoot% to "C:\Windows")
6 | [v] Parent Process: wininit.exe or winlogon.exe (xp)
7 | [~] Check for similar names (just a try...)
8 |
9 | Francesco "dfirfpi" Picasso
10 | 2015-02-12T15:57:37
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | lsass.exe
19 |
20 |
21 |
22 |
23 |
24 | winlogon.exe
25 |
26 |
27 |
28 | wininit.exe
29 |
30 |
31 |
32 |
33 | c:\windows\system32\lsass.exe
34 |
35 |
36 |
37 |
38 |
39 |
40 | lsa
41 |
42 |
43 |
44 | lsass.exe
45 |
46 |
47 |
48 |
49 |
50 |
51 | 100
52 |
53 |
54 | 50
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/generic/e747cd9d-2ed5-41fe-9e6a-64b49680eeca_unusual_path_shimcache.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | suspicious paths (executed)
5 | suspicious executable path extracted from ShimCache
6 | Takahiro Haruyama
7 | 2014-09-26T10:10:08Z
8 |
9 |
10 |
11 |
12 |
13 |
14 | \ProgramData
15 |
16 |
17 |
18 | \$Recycle.Bin
19 |
20 |
21 |
22 | \Windows\Temp
23 |
24 |
25 |
26 | \Users\All Users
27 |
28 |
29 |
30 | \Users\Default
31 |
32 |
33 |
34 | \Users\Public
35 |
36 |
37 |
38 | \\Users\\.*\\AppData
39 |
40 |
41 |
42 |
43 |
44 | on
45 |
46 |
47 | on
48 |
49 | ononononon
50 |
51 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/specific/ec7eed9a-d266-4443-9333-0234cca0f682_equation_proc.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | EquationDrug HDD/SSD firmware operation (process)
5 | nls_933w.dll/win32m.sys
6 | https://securelist.com/blog/research/69203/inside-the-equationdrug-espionage-platform/
7 | Takahiro Haruyama
8 | 2015-04-27T11:01:32
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | \xc0\x21\x00\x87
17 |
18 |
19 |
20 | \xc4\x21\x00\x87
21 |
22 |
23 |
24 | \xc8\x21\x00\x87
25 |
26 |
27 |
28 | \xcc\x21\x00\x87
29 |
30 |
31 |
32 | \xd0\x21\x00\x87
33 |
34 |
35 |
36 | \xd4\x21\x00\x87
37 |
38 |
39 |
40 |
41 |
42 | \x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x07\xec
43 |
44 |
45 |
46 | \x00\x00\x00\x00\x01\x57\x00\x00\x00\x00\x02\x44\x00\x00\x00\x00\x03\x43\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x06\xa0\x00\x00\x00\x00\x07\x8a
47 |
48 |
49 |
50 | \x00\x00\x00\x00\x01\x57\x00\x00\x00\x00\x02\x44\x00\x00\x00\x00\x03\x43\x00\x00\x00\x00\x04\x0e\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x06\xa0\x00\x00\x00\x00\x07\x91
51 |
52 |
53 |
54 |
55 | IoControlCodeATA data sequence
56 |
57 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/IOCs/specific/fb4064f7-8fcd-4a81-9584-cd874c365d12_equation_driver.ioc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | EquationDrug HDD/SSD firmware operation (kernel)
5 | nls_933w.dll/win32m.sys
6 | https://securelist.com/blog/research/69203/inside-the-equationdrug-espionage-platform/
7 | Takahiro Haruyama
8 | 2015-04-28T06:33:48
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | \xc0\x21\x00\x87
17 |
18 |
19 |
20 | \xc4\x21\x00\x87
21 |
22 |
23 |
24 | \xc8\x21\x00\x87
25 |
26 |
27 |
28 | \xcc\x21\x00\x87
29 |
30 |
31 |
32 | \xd0\x21\x00\x87
33 |
34 |
35 |
36 | \xd4\x21\x00\x87
37 |
38 |
39 |
40 |
41 | \x8A\x53\xFF\x80\xFA\xFF\x75\x1D\x8D\x43\xFB\x39\x08\x75\x32\xF6\x03\x04
42 |
43 |
44 |
45 | IoControlCodecode parsing ATA data seq
46 |
47 |
--------------------------------------------------------------------------------
/TakahiroHaruyama/PyIOCe_templates/indicator_terms.volatility:
--------------------------------------------------------------------------------
1 | {"volatility": {"FileItem/FileExtension": {"last_modified": "2014-11-14T03:05:26", "context_doc": "FileItem", "content_type": "string"}, "DriverItem/TimerRoutineIncluded": {"last_modified": "2014-09-30T08:30:45", "context_doc": "DriverItem", "content_type": "string"}, "ServiceItem/cmdLine": {"last_modified": "2014-09-30T08:34:17", "context_doc": "ServiceItem", "content_type": "string"}, "ProcessItem/cmdLine": {"last_modified": "2015-02-18T06:53:21", "context_doc": "ProcessItem", "content_type": "string"}, "ProcessItem/Hooked/API/HookingModuleName": {"last_modified": "2015-02-24T09:40:49", "context_doc": "ProcessItem", "content_type": "string"}, "RegistryItem/ShimCache/ExecutablePath": {"last_modified": "2014-09-30T08:33:39", "context_doc": "RegistryItem", "content_type": "string"}, "DriverItem/StringList/string": {"last_modified": "2014-09-30T08:30:41", "context_doc": "DriverItem", "content_type": "string"}, "FileItem/FullPath": {"last_modified": "2014-11-14T03:05:50", "context_doc": "FileItem", "content_type": "string"}, "ProcessItem/PortList/PortItem/localIP": {"last_modified": "2014-09-30T08:31:44", "context_doc": "ProcessItem", "content_type": "string"}, "FileItem/SizeInBytes": {"last_modified": "2014-11-14T03:07:09", "context_doc": "FileItem", "content_type": "int"}, "ProcessItem/ParentProcessName": {"last_modified": "2014-09-30T08:31:38", "context_doc": "ProcessItem", "content_type": "string"}, "ProcessItem/hidden": {"last_modified": "2014-09-30T08:32:36", "context_doc": "ProcessItem", "content_type": "string"}, "HookItem/SSDT/HookedFunctionName": {"last_modified": "2014-09-30T08:30:55", "context_doc": "HookItem", "content_type": "string"}, "FileItem/FileName": {"last_modified": "2014-11-14T03:05:42", "context_doc": "FileItem", "content_type": "string"}, "ProcessItem/PortList/PortItem/localPort": {"last_modified": "2014-09-30T08:31:51", "context_doc": "ProcessItem", "content_type": "int"}, "RegistryItem/Path": {"last_modified": "2014-09-30T08:33:08", "context_doc": "RegistryItem", "content_type": "string"}, "ProcessItem/SectionList/MemorySection/PEInfo/ImportedModules/Module/ImportedFunctions/string": {"last_modified": "2014-09-30T08:32:15", "context_doc": "ProcessItem", "content_type": "string"}, "FileItem/INode": {"last_modified": "2014-11-14T03:05:58", "context_doc": "FileItem", "content_type": "int"}, "ProcessItem/StringList/string": {"last_modified": "2014-09-30T08:32:22", "context_doc": "ProcessItem", "content_type": "string"}, "ProcessItem/PortList/PortItem/remoteIP": {"last_modified": "2014-09-30T08:31:56", "context_doc": "ProcessItem", "content_type": "string"}, "DriverItem/PEInfo/ImportedModules/Module/ImportedFunctions/string": {"last_modified": "2014-09-30T08:30:38", "context_doc": "DriverItem", "content_type": "string"}, "ProcessItem/EnabledPrivilege/Name": {"last_modified": "2014-09-30T08:31:10", "context_doc": "ProcessItem", "content_type": "string"}, "ProcessItem/Hooked/API/FunctionName": {"last_modified": "2014-09-30T08:31:33", "context_doc": "ProcessItem", "content_type": "string"}, "ProcessItem/HandleList/Handle/Type": {"last_modified": "2014-09-30T08:31:22", "context_doc": "ProcessItem", "content_type": "string"}, "ServiceItem/descriptiveName": {"last_modified": "2014-09-30T08:34:23", "context_doc": "ServiceItem", "content_type": "string"}, "ProcessItem/DllHidden": {"last_modified": "2015-02-24T07:46:59", "context_doc": "ProcessItem", "content_type": "string"}, "ProcessItem/PortList/PortItem/remotePort": {"last_modified": "2014-09-30T08:32:02", "context_doc": "ProcessItem", "content_type": "int"}, "ProcessItem/SectionList/MemorySection/InjectedHexPattern": {"last_modified": "2015-02-26T03:51:12", "context_doc": "ProcessItem", "content_type": "string"}, "ServiceItem/name": {"last_modified": "2014-09-30T08:34:29", "context_doc": "ServiceItem", "content_type": "string"}, "DriverItem/IRP/HookingModuleName": {"last_modified": "2014-09-30T08:30:35", "context_doc": "DriverItem", "content_type": "string"}, "DriverItem/DriverName": {"last_modified": "2014-09-30T08:30:32", "context_doc": "DriverItem", "content_type": "string"}, "ProcessItem/HandleList/Handle/Name": {"last_modified": "2014-09-30T08:31:15", "context_doc": "ProcessItem", "content_type": "string"}, "ProcessItem/DllPath": {"last_modified": "2014-09-30T08:31:06", "context_doc": "ProcessItem", "content_type": "string"}, "ProcessItem/SectionList/MemorySection/Injected": {"last_modified": "2014-09-30T08:32:07", "context_doc": "ProcessItem", "content_type": "string"}, "ProcessItem/name": {"last_modified": "2014-09-30T08:32:50", "context_doc": "ProcessItem", "content_type": "string"}, "DriverItem/CallbackRoutine/Type": {"last_modified": "2014-09-30T08:30:29", "context_doc": "DriverItem", "content_type": "string"}}}
--------------------------------------------------------------------------------
/TakahiroHaruyama/PyIOCe_templates/parameters.volatility:
--------------------------------------------------------------------------------
1 | {"volatility": {"note": {"last_modified": "2014-11-14T09:08:21", "value_type": "string"}, "score": {"last_modified": "2014-11-14T09:08:25", "value_type": "string"}, "detail": {"last_modified": "2014-10-23T10:04:27", "value_type": "string"}}}
--------------------------------------------------------------------------------
/TakahiroHaruyama/README.md:
--------------------------------------------------------------------------------
1 | Author: Takahiro Haruyama
2 |
3 | See https://github.com/TakahiroHaruyama for updates and license information.
--------------------------------------------------------------------------------
/TakahiroHaruyama/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/TeamDecepticon/[VAC] 2018_REPORT_DECEPTICON.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/TeamDecepticon/[VAC] 2018_REPORT_DECEPTICON.pdf
--------------------------------------------------------------------------------
/TeamMalGround/2018 Volatility Analysis Contest Report_MalGround.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/TeamMalGround/2018 Volatility Analysis Contest Report_MalGround.pdf
--------------------------------------------------------------------------------
/Team_HSLFL/[VAC2019] Report - Team HSLFS.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/Team_HSLFL/[VAC2019] Report - Team HSLFS.pdf
--------------------------------------------------------------------------------
/ThomasChopitea/README.md:
--------------------------------------------------------------------------------
1 | Author: Thomas Chopitea
2 |
3 | See https://github.com/tomchop for updates and license information.
--------------------------------------------------------------------------------
/ThomasChopitea/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ThomasWhite/README.md:
--------------------------------------------------------------------------------
1 | Author: Thomas White
2 |
3 | See https://github.com/tribalchicken for updates and license information.
--------------------------------------------------------------------------------
/ThomasWhite/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ThomasWhite/filevault2.py:
--------------------------------------------------------------------------------
1 | """
2 | @author: Thomas White
3 | @license: GNU General Public License 2.0
4 | @contact: thomas@tribalchicken.com.au
5 | @organization:
6 | """
7 |
8 | import volatility.obj as obj
9 | import volatility.plugins.mac.pstasks as pstasks
10 | import volatility.plugins.mac.common as common
11 | import volatility.utils as utils
12 |
13 |
14 | class mac_filevault2(pstasks.mac_tasks):
15 | """ Attempts to recover FileVault 2 Volume Master Keys """
16 |
17 | def calculate(self):
18 | common.set_plugin_members(self)
19 | procs = pstasks.mac_tasks.calculate(self)
20 |
21 | for proc in procs:
22 | if str(proc.p_comm) != "kernel_task":
23 | continue
24 |
25 | proc_as = proc.get_process_address_space()
26 |
27 | for map in proc.get_proc_maps():
28 | if not map.get_perms() == 'r--':
29 | continue
30 |
31 | address = map.links.start
32 |
33 | Vmk1 = proc_as.read(address,16)
34 | Vmk2 = proc_as.read(address + 0x430,16) #Note: Vmk2 refers to our second instance of the VMK, not the tweak key.
35 |
36 | signature = obj.Object("unsigned int", offset = address, vm = proc_as)
37 |
38 | if not Vmk1 or signature == 0x0:
39 | continue
40 |
41 | if Vmk1 == Vmk2:
42 | yield address, Vmk1
43 |
44 | def unified_output(self, data):
45 | return TreeGrid([("Address", Address),
46 | ("Volume Master Key", str)
47 | ], self.generator(data))
48 |
49 | def generator(self, data):
50 | for (address, Vmk1) in data:
51 | vmk = []
52 | for o, h, c in utils.Hexdump(Cmp1):
53 | vmk.append(h)
54 | yield(0, [Address(address),str(''.join(vmk).replace(" ","")),])
55 |
56 |
57 | def render_text(self, outfd, data):
58 | self.table_header(outfd, [("Address", "#018x"),
59 | ("Volume Master Key", "32")])
60 | for (address, Vmk1) in data:
61 | vmk = []
62 | for o, h, c in utils.Hexdump(Vmk1):
63 | vmk.append(h)
64 |
65 | self.table_row(outfd,
66 | address,
67 | ''.join(vmk).replace(" ","")
68 | )
69 |
--------------------------------------------------------------------------------
/TomSpencer/README.md:
--------------------------------------------------------------------------------
1 | Author: Tom Spencer
2 |
3 | See https://github.com/tomspencer for updates and license information.
--------------------------------------------------------------------------------
/TomSpencer/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/TranVienHa/README.md:
--------------------------------------------------------------------------------
1 | Author: Tran Vien Ha
2 |
3 | See https://github.com/tranvienha/volatility-osint for updates and licensing information.
--------------------------------------------------------------------------------
/TranVienHa/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/TranVienHa/osint.conf:
--------------------------------------------------------------------------------
1 | [DEFAULT]
2 | SITEREVIEW_URL=http://sitereview.bluecoat.com/rest/categorization
3 | VIRUSTOTAL_URL=https://www.virustotal.com/vtapi/v2/url/report
4 | VIRUSTOTAL_TOKEN=
5 | MISP_URL=
6 | MISP_TOKEN=
7 |
--------------------------------------------------------------------------------
/TranVienHa/whitelist.txt:
--------------------------------------------------------------------------------
1 | .apple.com
2 | .bing.com
3 | .entrust.com
4 | .entrust.net
5 | .freedesktop.org
6 | .globalsign.net
7 | .google.com
8 | .hotmail.com
9 | .java.com
10 | .jquery.com
11 | .live.com
12 | .microsoft.com
13 | .msn.com
14 | .python.org
15 | .realtek.com
16 | .sun.com
17 | .verisign.com
18 | .vmware.com
19 | .w3.org
20 | .windowsupdate.com
21 | .xmlsoap.org
22 | .yahoo.com
23 |
--------------------------------------------------------------------------------
/WMDF/README.md:
--------------------------------------------------------------------------------
1 | Author: Hemant Kumar and Sajeev Nair
2 |
3 | See goo.gl/XC177B to download the framework
--------------------------------------------------------------------------------
/WMDF/WMDF.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/WMDF/WMDF.pdf
--------------------------------------------------------------------------------
/WindowsToastNotifications/20190927_Toast Notifications_Writeup.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/WindowsToastNotifications/20190927_Toast Notifications_Writeup.pdf
--------------------------------------------------------------------------------
/WindowsToastNotifications/README.md:
--------------------------------------------------------------------------------
1 | Author: Rolf Govers and Max de Bruijn
--------------------------------------------------------------------------------
/WindowsToastNotifications/toastplugin.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """
3 | Requires Yara-python to be installed
4 | """
5 | __authors__ = "Max de Bruijn , Rolf Govers"
6 | __department__ = "Forensics and Incident Response"
7 | __company__ = "Fox-IT B.V."
8 | __year__ = "2019"
9 | __version__ = "1.0"
10 | __status__ = "Final Volatility Plugin contest submission"
11 |
12 |
13 | import volatility.plugins.common as common
14 | import volatility.plugins.malware.malfind as malfind
15 | import volatility.utils as utils
16 | import volatility.win32 as win32
17 | import volatility.debug as debug
18 | from volatility.renderers import TreeGrid
19 | from volatility.renderers.basic import Address
20 | import yara
21 | import os
22 |
23 | try:
24 | import yara
25 | has_yara = True
26 | except ImportError:
27 | has_yara = False
28 |
29 |
30 |
31 | class toastPlugin(common.AbstractWindowsCommand):
32 |
33 |
34 | def generator(self,data):
35 | for proc, address, hit, content in data:
36 | relevantContent = content.split('/toast>')[0]+'/toast>'
37 | yield(0,[Address(address),str(proc.ImageFileName),relevantContent])
38 |
39 | def unified_output(self,data):
40 | tree = [("Address",Address),
41 | ("ProcessName",str),
42 | ("ToastXML",str)]
43 | return TreeGrid(tree,self.generator(data))
44 |
45 |
46 | def calculate(self):
47 | if not has_yara:
48 | debug.error("Yara must be installed for this plugin")
49 | addr_space = utils.load_as(self._config)
50 | tasks = win32.tasks.pslist(addr_space)
51 | for proc in tasks:
52 | if str(proc.ImageFileName) == "explorer.exe":
53 | rules = yara.compile(sources = {
54 | 'n':'rule toast {strings: $a=// condition: $a}'
55 | })
56 | scanner = malfind.VadYaraScanner(task=proc, rules=rules)
57 | for hit,address in scanner.scan(maxlen=0x40000000):
58 | yield (proc, address, hit, scanner.address_space.zread(address, 0x4000))
59 |
--------------------------------------------------------------------------------
/WyattRoersma/README.md:
--------------------------------------------------------------------------------
1 | Author: Wyatt Roersma
2 |
3 | See https://github.com/wroersma for updates and license information.
--------------------------------------------------------------------------------
/WyattRoersma/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/YingLi/README.md:
--------------------------------------------------------------------------------
1 | Author: Ying Li
2 |
3 | See https://github.com/cyli for updates and license information.
--------------------------------------------------------------------------------
/YingLi/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/YingLi/__init__.py
--------------------------------------------------------------------------------
/ZeusScan/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/ZeusScan/__init__.py
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/aim4r/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015, @aim4r
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 |
25 |
--------------------------------------------------------------------------------
/aim4r/README.md:
--------------------------------------------------------------------------------
1 | Author: aim4r
2 |
3 | See https://github.com/aim4r for updates and license information.
--------------------------------------------------------------------------------
/aim4r/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/itayk/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamdfir/volatility-plugins-community/4306ba2cffe381536787375b5727b8d47d53bf8c/itayk/__init__.py
--------------------------------------------------------------------------------