├── .gitignore ├── README.md ├── TECHNIQUE TEMPLATE.md └── hunts ├── analyze_producer_consumer_ratio.md ├── antivirus_logs.md ├── beacon_detection_via_intra_request_time_deltas.md ├── checking-how-outsiders-see-you.md ├── comparing_host_images_memory_dumps_to_known_good_baselines.md ├── critical_process_impersonation.md ├── dynamic_dns_c2.md ├── emet_log_mining.md ├── golden_ticket.md ├── http_uri_analysis.md ├── http_user_agent_analysis.md ├── internet_facing_http_request_analysis.md ├── lateral-movement-via-explicit-credentials.md ├── lateral-movement-windows-authentication-logs.md ├── lateral_movement_detection_via_process_monitoring.md ├── net_session_c2.md ├── ntfs_extended_attribute_analysis.md ├── privileged-group-tracking.md ├── psexec-windows-events.md ├── ram_dumping.md ├── rdp_external_access.md ├── renamed-tools.md ├── rogue_listeners.md ├── shimcache_amcache.md ├── suspicious_command_shells.md ├── suspicious_process_creation_via_windows_event_logs.md ├── webshell_behavior.md ├── webshells.md ├── whaling-detection-via-unusual-sender-domains.md ├── windows_autoruns_analysis.md ├── windows_driver_analysis.md ├── windows_prefetch_cache_analysis.md └── windows_service_analysis.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | #Ipython Notebook 62 | .ipynb_checkpoints 63 | 64 | *~ 65 | _site 66 | Gemfile.lock 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The ThreatHunting Project 2 | An informational repo about hunting for adversaries in your IT environment. 3 | 4 | Be sure to visit [ThreatHunting.net](http://threathunting.net) for more info about this repo. 5 | 6 | ## License 7 | Here's the deal, in plain English: 8 | 9 | This repo is here for the community. You are free to use it for personal or commercial use provided you attribute it in some visible manner. We suggest "Data provided by the ThreatHunting Project, https://github.com/ThreatHuntingProject/ThreatHunting" or something substantially similar. Please do include the URL, though, to help more people find us. 10 | 11 | -------------------------------------------------------------------------------- /TECHNIQUE TEMPLATE.md: -------------------------------------------------------------------------------- 1 | #Technique 2 | 3 | **Purpose**: 4 | 5 | **Data Required**: 6 | 7 | **Collection Considerations**: 8 | 9 | **Analysis Techniques**: 10 | 11 | **Description** 12 | 13 | **Other Notes** 14 | 15 | **More Info** 16 | 17 | - [insert link here]() 18 | -------------------------------------------------------------------------------- /hunts/analyze_producer_consumer_ratio.md: -------------------------------------------------------------------------------- 1 | #Producer-Consumer Ratio for Detecting Data Exfiltration 2 | 3 | **Purpose**: Find changes in traffic flows that indicate exfil 4 | 5 | **Data Required**: session data (argus, netflow/ipfix, or bro-logs) 6 | 7 | **Collection Considerations**: 8 | 9 | **Analysis Techniques**: Identify changes in host roles, and investigate. PCR is 10 | a normalized metric of traffic ratios and from a host ranging from -1 to 1. 11 | 12 | | PCR | host role | 13 | | ---: | --------- | 14 | | 1.0 | pure push - FTP upload, multicast, beaconing | 15 | | 0.4 | 70:30 export - Sending Email | 16 | | 0.0 | Balanced Exchange - NTP, ARP probe | 17 | | -0.5 | 3:1 import - HTTP Browsing | 18 | | -1.0 | pure pull - HTTP Download | 19 | 20 | **Description** 21 | 22 | The Producer-Consumer Ratio metric introduced at [FlowCON](http://qosient.com/argus/presentations/Argus.FloCon.2014.PCR.Presentation.pdf) by Carter Bullard and John Gerth is defined as: 23 | 24 | ( SrcApplicationBytes - DstApplicationBytes ) 25 | PCR = --------------------------------------------- 26 | ( SrcApplicationBytes + DstApplicationBytes ) 27 | 28 | where: 29 | 30 | Application Bytes = (Total Bytes ⎼ Sum( L[2,3,4] Headers )) - Retrans Bytes 31 | 32 | DNS is less noisy than HTTP for this metric, and is a possible exfil channel. A 33 | positive shift in PCR for DNS traffic may indicate DNS Exfil. 34 | 35 | 36 | **Other Notes** 37 | 38 | 39 | **More Info** 40 | 41 | - [PCR - A New Flow Metric, FloCon 2014](http://qosient.com/argus/presentations/Argus.FloCon.2014.PCR.Presentation.pdf) 42 | - [Leveraging Metadata And Machine Learning To Enhance Intrusion Analysis](http://spotidoc.com/doc/367670/leveraging-metadata-and-machine-learning) 43 | - [Github: reservoirlabs/bro-producer-consumer-ratio](https://github.com/reservoirlabs/bro-producer-consumer-ratio) 44 | - [Detecting Data Staging & Exfil Using the Producer-Consumer Ratio](http://detect-respond.blogspot.com/2016/09/detecting-data-staging-exfil-using-PCR-shift.html) 45 | -------------------------------------------------------------------------------- /hunts/antivirus_logs.md: -------------------------------------------------------------------------------- 1 | # Finding Known-Bad in Antivirus Logs 2 | 3 | **Purpose**: Identify things that the AV system has found that you particularly care about 4 | 5 | **Data Required**: Endpoint security logs (AV); List of "bad things" to look for. 6 | 7 | **Collection Considerations**: 8 | 9 | **Analysis Techniques**: String matching 10 | 11 | **Description** 12 | 13 | If you collect all your endpoint security logs in one place, you can search them for specific strings that correspond to things you're particularly interested in finding. In other words, things you may want to treat as _more important_ than normal alerts the endpoint security tool may already be creating. 14 | 15 | Examples of types of strings to look for: 16 | 17 | * Known webshell filenames 18 | * Anything running under a system directory (%WINDOWS%, %RECYCLER%) or other unusual locations (the webroot) 19 | * AV "street names" you are concerned about 20 | * Packed executables (if this information is logged) 21 | * Known attacker tools (cred dumpers, scanners, etc) 22 | * Any detection with the string "dropper" in the name 23 | 24 | **More Info** 25 | 26 | * [Intrusion Hunting for the Masses - David Sharpe (HackMiami 2016)](https://www.youtube.com/watch?v=YLgycMCPo4c) 27 | * [Seek Evil, and Ye Shall Find: A Guide to Cyber Threat Hunting Operations](https://digitalguardian.com/blog/seek-evil-and-ye-shall-find-guide-cyber-threat-hunting-operations), Tim Bandos, Digital Guardian 28 | 29 | 30 | -------------------------------------------------------------------------------- /hunts/beacon_detection_via_intra_request_time_deltas.md: -------------------------------------------------------------------------------- 1 | #Beacon Detection via Intra-Request Time Deltas 2 | 3 | **Purpose**: Find regular HTTP beaconing behavior which may indicate malware C2 4 | 5 | **Data Required**: HTTP proxy logs 6 | 7 | **Collection Considerations**: 8 | 9 | **Analysis Techniques**: Visualization (Bar graphs) 10 | 11 | **Description** 12 | 13 | Malware C2 often utilizes regular request intervals ("beacons") to maintain control with the attacker's infrastructure. By examining the intra-request times between requests to the same resource by the same source IP and visualizing the results, you can look for patterns of regular activity. 14 | 15 | **Other Notes** 16 | 17 | 18 | **More Info** 19 | 20 | - [Detecting Malware Beacons Using Splunk](http://pleasefeedthegeek.wordpress.com/2012/12/20/detecting-malware-beacons-using-splunk/) 21 | 22 | - [Tweet by @jackcr](https://twitter.com/jackcr/status/747786867093946368) 23 | -------------------------------------------------------------------------------- /hunts/checking-how-outsiders-see-you.md: -------------------------------------------------------------------------------- 1 | #Checking How Outsiders See You 2 | 3 | **Purpose**: Determine whether any of your web sites are serving malware by using third party opinions 4 | 5 | **Data Required**: A list of your Internet-facing domain names and websites 6 | 7 | **Collection Considerations**: You will need a Google Safebrowsing API key to query their service 8 | 9 | **Analysis Techniques**: None 10 | 11 | **Description** 12 | Query the Google Safebrowsing database (or others) for their opinions on your own websites. 13 | 14 | **Other Notes** 15 | 16 | **More Info** 17 | 18 | - [Threat Hunting for the Masses](https://www.youtube.com/watch?v=YLgycMCPo4c), David Sharpe, HackMiami 2016 19 | 20 | -------------------------------------------------------------------------------- /hunts/comparing_host_images_memory_dumps_to_known_good_baselines.md: -------------------------------------------------------------------------------- 1 | #Comparing Host Images/Memory Dumps to Known-Good Baselines 2 | 3 | **Purpose**: Identify deviations from "known-good" which might tend to indicate the presence of malware on a system 4 | 5 | **Data Required**: Memory dumps, Registry dumps, "known good" data 6 | 7 | **Collection Considerations**: This works best when tracked over time rather than as a single comparison. Volatility plugins such as "stalker", "profiler", "regcomp" & "hunter" are useful 8 | 9 | **Analysis Techniques**: 10 | 11 | **Description** 12 | 13 | **Other Notes** 14 | 15 | **More Info** 16 | 17 | - [Every Step You Take](http://downloads.volatilityfoundation.org/omfw/2013/OMFW2013_Levy.pdf) (*video needed, if available*) 18 | - “Several Ways to Skin a Rat", Jamie "Gleeda” Levy (*Link needed*) 19 | 20 | -------------------------------------------------------------------------------- /hunts/critical_process_impersonation.md: -------------------------------------------------------------------------------- 1 | # Finding Malware Process Impersonation via String Distance 2 | 3 | **Purpose** 4 | 5 | Finds malware attempting to hide execution by running with names which are confusingly similar to legitimate system processes. 6 | 7 | **Data Required** 8 | 9 | Endpoint process creation data 10 | 11 | **Collection Considerations** 12 | 13 | None 14 | 15 | **Analysis Techniques** 16 | 17 | Scripting 18 | 19 | **Description** 20 | 21 | A popular technique for hiding malware running on Windows systems is to give it a name that's confusingly similar to a legitimate Windows process, preferably one that is always present on all systems. Using a _string similarity_ algorithm ([Damerau-Levenshtein](https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance) distance), we can compare the names of running processes to a set of defined Windows system processes to look for this sort of impersonation. 22 | 23 | **Other Notes** 24 | 25 | None 26 | 27 | **More Info** 28 | 29 | - [Hunting for Malware Critical Process Impersonation](http://detect-respond.blogspot.com/2016/11/hunting-for-malware-critical-process.html) -------------------------------------------------------------------------------- /hunts/dynamic_dns_c2.md: -------------------------------------------------------------------------------- 1 | #C2 via Dynamic DNS 2 | 3 | **Purpose**: Identify potential C2 activity 4 | 5 | **Data Required** 6 | 7 | Outgoing logs that contain info about domains 8 | visited by internal clients, such as DNS query or HTTP proxy logs. 9 | 10 | You will also need a list of dynamic DNS provider domain names. 11 | 12 | **Collection Considerations** 13 | 14 | None 15 | 16 | **Analysis Techniques** 17 | Filtering, stack counting 18 | 19 | **Description** 20 | 21 | Isolate the log entries that contain domains hosted on dynamic DNS 22 | providers. Look for sites visited by a low number of unique hosts (IP 23 | addresses). Utilize a lookup or feed of known dynamic DNS (DDNS) domains 24 | to query against data in a SIEM or log aggregator. 25 | 26 | **Other Notes** 27 | 28 | In many business environments, _any_ access to a dynamic DNS provider 29 | may be at least somewhat suspicious. 30 | 31 | **More Info** 32 | 33 | - [Seek Evil, and Ye Shall Find: A Guide to Cyber Threat Hunting Operations](https://digitalguardian.com/blog/seek-evil-and-ye-shall-find-guide-cyber-threat-hunting-operations), Tim Bandos, Digital Guardian 34 | - [www.malwaredomains.com Dynamic DNS domain list](http://mirror1.malwaredomains.com/files/dynamic_dns.txt), Malwaredomains.com 35 | 36 | -------------------------------------------------------------------------------- /hunts/emet_log_mining.md: -------------------------------------------------------------------------------- 1 | #EMET Log Mining 2 | 3 | **Purpose**: Identify potential 0-day exploits by looking for things blocked by EMET 4 | 5 | **Data Required**: Windows Application Event logs (which contain EMET logs) 6 | 7 | **Collection Considerations**: 8 | 9 | **Analysis Techniques**: 10 | 11 | **Description** 12 | 13 | Window's Enhanced Mitigation Experience Toolkit (EMET) is a set of technologies that monitor for and block certain conditions that commonly arise as the result of common exploit patterns. It's commonly used on endpoints (but is also available on servers). 14 | 15 | The idea here is to examine the EMET logs to find things that it has blocked (processes it has killed before they could become dangerous). These may be simple bugs in legit applications, or they could be indications of exploit attempts. 16 | 17 | **Other Notes** 18 | 19 | It's not clear what actual analysis techniques might be useful here yet, short of simply examining every EMET log individually. Need more research on this one. 20 | 21 | **More Info** 22 | 23 | * [Intrusion Hunting for the Masses](https://www.youtube.com/watch?v=YLgycMCPo4c), David Sharpe (HackMiami 2016) 24 | 25 | 26 | -------------------------------------------------------------------------------- /hunts/golden_ticket.md: -------------------------------------------------------------------------------- 1 | # Finding Golden and Silver Tickets 2 | 3 | **Purpose** 4 | 5 | Identify suspicious TGT (Golden) and TGS (Silver) tickets by comparing the MaxTicketAge from the domain policy to the difference in the StartTime and EndTime of the cached authentication ticket. 6 | 7 | **Data Required** 8 | 9 | Remote Access to collect susicious tickets OR 10 | Schedule task to write possible bad tickets to application event log for log/SIEM review 11 | 12 | **Collection Considerations** 13 | 14 | Consider running local scripts and collecting the application event log rather than a scan to reduce noise 15 | See [here](https://github.com/spohara79/TGT---Golden-Silver-Ticket) 16 | 17 | **Analysis Techniques**: 18 | 19 | Comparative time analysis of domain policy vs cached tickets 20 | 21 | **Description** 22 | 23 | * Retrieve the Kerberos MaxTicketAge from the GPO / Domain Policy 24 | * Use `klist.exe sessions` to view the cached sessions 25 | * view the TGT or TGS tickets using `klist tgt -li ` or `klist tickets -li internal messages as well as the internal -> internal messages. 8 | 9 | **Analysis Techniques**: filtering, comparing list membership 10 | 11 | **Description** 12 | From the original source: 13 | 14 | *To grasp this idea, we must establish parts of the sender and recipient email address. Using john.smith@contoso.com email address as an example, contoso.com would be the domain. And if the email was sent from john.smith@contoso.com to ashley.johnson@example.com then we would refer to contoso.com as the sender domain and example.com as the recipient domain.* 15 | 16 | *Whaling Detection works by building a list of the sender domains sent to the high-profile employees and alerting on any emails when the sender domain is not found in these three sections:* 17 | 18 | * Emails the high-profile employees composed themselves (recipient domain) 19 | * Emails sent to non-high-profile employees 20 | * Emails composed by non-high-profile employees (recipient domain) 21 | 22 | **Other Notes** 23 | Psuedocode for a whaling rule, also from the original source: 24 | 25 | *ALERT: Recipient=HPE & Sender NOT IN (HPE_Composed_Domains OR NonHPE_Composed_Domains OR Sender_Domains_To_NonHPE)* 26 | 27 | **More Info** 28 | 29 | - [Whaling Detection](https://tech.target.com/2019/06/07/Whaling-Detection.html) 30 | -------------------------------------------------------------------------------- /hunts/windows_autoruns_analysis.md: -------------------------------------------------------------------------------- 1 | #Autoruns Analysis 2 | 3 | **Purpose**: Find malware persistence by examining common mechanisms across a network 4 | 5 | **Data Required**: List of programs configured to start at boot/logon time on each endpoint 6 | 7 | **Collection Considerations**: MS Sysinternals' `autorunsc.exe` is the most common way to collect this from a host 8 | 9 | **Analysis Techniques**: Stack counting, string matching, outlier detection 10 | 11 | **Description** 12 | 13 | Gather autoruns data from endpoints across the network and look for: 14 | 15 | * Executable starting out of `c:programdata`, recycle bin, appdata area, `%temp%` 16 | * Unsigned executables 17 | * Shortest / longest filenames 18 | * GUID filenames 19 | * Rare executable filenames or directories 20 | 21 | 22 | **More Info** 23 | 24 | * [Intrusion Hunting for the Masses](https://www.youtube.com/watch?v=YLgycMCPo4c), David Sharpe (HackMiami 2016) 25 | * [CAR-2013-01-002: Autorun Differences](https://car.mitre.org/wiki/CAR-2013-01-002), MITRE Cyber Analytic Repository 26 | -------------------------------------------------------------------------------- /hunts/windows_driver_analysis.md: -------------------------------------------------------------------------------- 1 | #Windows Driver Analysis 2 | 3 | **Purpose**: Find malware running in Windows drivers across a network 4 | 5 | **Data Required**: List of drivers loaded on each endpoint 6 | 7 | **Collection Considerations**: Typically use the `driverquery` command on each host. 8 | 9 | **Analysis Techniques**: Stack counting 10 | 11 | **Description** 12 | 13 | Examine driver entries for: 14 | 15 | * Impossible, zeroed or garbage link dates 16 | * Stack each binary image and look for unusual link dates 17 | * Unusual filenames or locations of binaries 18 | * Rare descriptions 19 | * Incorrect descriptions (grammar, typos, punctuation, etc) 20 | * Rare display names 21 | * Missing, invalid or unusual digital signatures 22 | 23 | **More Info** 24 | 25 | * [Intrusion Hunting for the Masses](https://www.youtube.com/watch?v=YLgycMCPo4c), David Sharpe (HackMiami 2016) 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /hunts/windows_prefetch_cache_analysis.md: -------------------------------------------------------------------------------- 1 | #Windows Prefetch Cache Analysis 2 | 3 | **Purpose**: Identify malware or other suspicious executables that ran on a system. 4 | 5 | **Data Required**: Windows prefetch cache data 6 | 7 | **Collection Considerations**: Requires a special tool to convert binary file format to something we can consume (e.g., Nirsoft `WinPrefetchView`. Probably needs an agent. 8 | 9 | **Analysis Techniques**: Stack counting, outlier detection 10 | 11 | **Description** 12 | 13 | Whenever any process executes on a Windows system, Windows writes an entry to the Prefetch cache. This actually supports an internal mechanism that tries to keep frequently-used binaries quickly accessible to increase performance, but it's good for hunting because it records info about what commands were recently run. 14 | 15 | This capability is present on all Windows versions starting with XP, though it is not enabled by default on Windows Server, so mostly this will apply to user endpoints. Also, for hardware reasons, it's usually disabled for systems with SSDs. 16 | 17 | From XP to Windows 7, the default limit was 128 files. This was increased to 1024 starting with Windows 8. 18 | 19 | Here's a sample prefetch record (format is tool-dependent, but they should all include the same info): 20 | 21 | 22 | Filename : DLLHOST.EXE-61F58501.pf 23 | Created Time : 9/9/2015 6:15:41 PM 24 | Modified Time : 9/9/2015 6:15:41 PM 25 | File Size : 5,726 26 | Process EXE : DLLHOST.EXE 27 | Process Path : C:WindowsSystem32dllhost.exe 28 | Run Counter : 1 29 | Last Run Time : 9/9/2015 6:15:08 PM 30 | Missing Process : No 31 | 32 | 33 | Stack the various fields and look for: 34 | 35 | * Unusual filenames and process EXE values (be sure to ignore the "-61F58501.pf" part, which is not relevant) 36 | * Same names but with unusual create/modify times or file sizes 37 | * Known-bad filenames & locations 38 | * Unusual executable locations 39 | * Unusually short / long names in filename or process EXE fields 40 | 41 | These are often suspicious, especially if the run count is very low (like 1). 42 | 43 | Order commands on each host by run time and look for: 44 | 45 | * Unusual combinations of commands (e.g., "net" followed closely by "ping", "at" or similar). 46 | 47 | **Other Notes** 48 | 49 | Order commands on each host by run time and look for: 50 | 51 | * Commands run at unusual times for each host 52 | 53 | **More Info** 54 | 55 | * [Intrusion Hunting for the Masses](https://www.youtube.com/watch?v=YLgycMCPo4c), David Sharpe (HackMiami 2016) 56 | 57 | 58 | -------------------------------------------------------------------------------- /hunts/windows_service_analysis.md: -------------------------------------------------------------------------------- 1 | #Windows Service Analysis 2 | 3 | **Purpose**: Find suspicious Windows services running across a network 4 | 5 | **Data Required**: Info about running services on endpoints; For `svchost` services, list of DLLs loaded inside 6 | 7 | **Collection Considerations**: May need a host agent (e.g., MS Sysinternals `psservice.exe` and `listdlls.exe`) to collect this regularly. Some Windows systems log service configuration, start & stop events, which might also be useful. 8 | 9 | **Analysis Techniques**: Stack counting 10 | 11 | **Description** 12 | 13 | An example of the data returned by `psservice.exe` is: 14 | 15 | SERVICE_NAME: ALG 16 | DISPLAY_NAME: Applicaton Layer Gateway Service 17 | Provides support for 3rd party protocol plug-ins for Internet Connec+on Sharing 18 | 19 | TYPE : 10 WIN32_OWN_PROCESS 20 | START_TYPE : 3 DEMAND_START 21 | ERROR_CONTROL : 1 NORMAL 22 | BINARY_PATH_NAME : C:WINDOWSSystem32alg.exe 23 | LOAD_ORDER_GROUP : 24 | TAG :0 25 | DEPENDENCIES : 26 | SERVICE_START_NAME: NT AUTHORITYLocalService 27 | FAIL_RESET_PERIOD : 900 seconds 28 | FAILURE_ACTIONS : Restart DELAY: 120000 seconds 29 | : Restart DELAY: 300000 seconds 30 | : None DELAY: 0 seconds 31 | 32 | An example of _listdlls_ output is: 33 | 34 | svchost.exe pid: 620 35 | Com mand line: C:WindowsSystem32svchost.exe -k WerSvcGroup 36 | Base Size Path 37 | 0x70eb0000 0x1e000 c:windowssystem32wersvc.dll 38 | Verified: Invalid Signature 39 | Publisher: n/a 40 | Description: n/a 41 | Product: n/a Version: n/a File version: n/a 42 | 43 | Look for 44 | 45 | * Rare `SERVICE_NAME` or `DISPLAY_NAME` values 46 | * GUID service names 47 | * Random service names 48 | * Blank fields which normally hold values 49 | * Unusual directories in the `BINARY_PATH_NAME` 50 | 51 | For `svchost` services, list all DLLs loaded inside them (using `listdlls`) and look for: 52 | 53 | * Rare DLLs and/or locations 54 | * Unsigned DLLs or those with invalid signatures 55 | 56 | **More Info** 57 | 58 | * [Intrusion Hunting for the Masses](https://www.youtube.com/watch?v=YLgycMCPo4c), David Sharpe (HackMiami 2016) 59 | 60 | 61 | 62 | --------------------------------------------------------------------------------