├── Detection_Notebooks ├── DLL_Injection │ ├── DLL_Injection.tar.gz │ ├── DLL_Injection_CRT_Raw.ipynb │ ├── DLL_Injection_CRT_Transformed.ipynb │ ├── DLL_Injection_RTL_Raw.ipynb │ ├── DLL_Injection_RTL_Transformed.ipynb │ ├── DLL_Injection_Raw.ipynb │ └── DLL_Injection_Transformed.ipynb ├── Hook_Injection │ ├── Hook_Injection.tar.gz │ ├── Hook_Injection_Raw.ipynb │ └── Hook_Injection_Transformed.ipynb ├── Process_Hollow │ ├── Process_Hollowing.tar.gz │ ├── Process_Hollowing_Raw.ipynb │ └── Process_Hollowing_Transformed.ipynb ├── Process_Reimaging │ ├── Process_Reimaging_Raw.ipynb │ ├── process_reimaging.ipynb │ └── process_reimaging.tar.gz └── Reflective_DLL_Injection │ ├── Reflective_DLL_Injection.tar.gz │ ├── Reflective_DLL_Injection_Raw.ipynb │ └── Reflective_DLL_Injection_Transformed.ipynb └── README.md /Detection_Notebooks/DLL_Injection/DLL_Injection.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsecurity101/Detecting-Process-Injection-Techniques/3b77a4f1b374cd950a42a4fd680a32277effa61a/Detection_Notebooks/DLL_Injection/DLL_Injection.tar.gz -------------------------------------------------------------------------------- /Detection_Notebooks/DLL_Injection/DLL_Injection_CRT_Raw.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from openhunt.logparser import winlogbeat\n", 10 | "from pyspark.sql import SparkSession\n", 11 | "from pyspark.sql.functions import *" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 2, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "win = winlogbeat()\n", 21 | "spark = SparkSession.builder.appName(\"Process\").config(\"spark.sql.caseSensitive\", \"True\").getOrCreate()" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 3, 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "name": "stdout", 31 | "output_type": "stream", 32 | "text": [ 33 | "[+] Processing a Spark DataFrame..\n", 34 | "[+] Reading Mordor file..\n", 35 | "[+] Processing Data from Winlogbeat version 7..\n", 36 | "[+] DataFrame Returned !\n" 37 | ] 38 | } 39 | ], 40 | "source": [ 41 | "process_injection = win.extract_nested_fields(\"dll_injection_2020-01-12160439.json\",spark)" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 4, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "process_injection.createOrReplaceTempView(\"process_injection\")" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 5, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "DLL_Injection = spark.sql(\n", 60 | "'''\n", 61 | "SELECT \n", 62 | " b.computer_name,\n", 63 | " b.SourceImage,\n", 64 | " ltrim('0x', b.GrantedAccess) as granted_access,\n", 65 | " b.TargetImage,\n", 66 | " b.SourceProcessId,\n", 67 | " b.SourceProcessGUID,\n", 68 | " c.NewThreadId,\n", 69 | " b.TargetProcessId,\n", 70 | " b.TargetImage,\n", 71 | " c.StartFunction\n", 72 | "FROM process_injection c\n", 73 | "JOIN process_injection b\n", 74 | " ON c.SourceProcessGuid = b.SourceProcessGUID\n", 75 | " AND b.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 76 | " AND b.event_id = 10\n", 77 | "WHERE c.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 78 | " AND c.event_id = 8\n", 79 | " AND c.StartFunction = \"LoadLibraryA\" OR c.StartFunction = \"LoadLibraryW\"\n", 80 | "'''\n", 81 | ")\n" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 6, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "df = DLL_Injection.select(\"computer_name\", conv(DLL_Injection.granted_access, 16, 10).alias(\"granted_access\"), \"SourceImage\", \"SourceProcessGUID\", \"NewThreadId\", \"TargetProcessId\", \"TargetImage\")" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 7, 96 | "metadata": {}, 97 | "outputs": [], 98 | "source": [ 99 | "df.createOrReplaceTempView(\"df\")" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 8, 105 | "metadata": {}, 106 | "outputs": [ 107 | { 108 | "name": "stdout", 109 | "output_type": "stream", 110 | "text": [ 111 | "+------------------+--------------+-------------------------------------------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 112 | "|computer_name |granted_access|SourceImage |SourceProcessGUID |NewThreadId|TargetProcessId|TargetImage |\n", 113 | "+------------------+--------------+-------------------------------------------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 114 | "|win10.marvel.local|2097151 |C:\\Users\\thor\\Downloads\\injection-master\\injection-master\\InjectDLL\\x64\\Debug\\InjectDLL.exe|{9d556bd4-b423-5e1b-0000-00104e060d01}|3004 |8288 |C:\\WINDOWS\\system32\\notepad.exe|\n", 115 | "+------------------+--------------+-------------------------------------------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 116 | "\n" 117 | ] 118 | } 119 | ], 120 | "source": [ 121 | "eid_8_10_minimal_privileges = spark.sql(\n", 122 | "'''\n", 123 | "SELECT * FROM df WHERE ((INT(granted_access) & 5170) == 5170) -- 5170 is decimal for (0x143A). The minimal privileges you need to obtain a handle in the target process PROCESS_CREATE_THREAD (0x0002) PROCESS_QUERY_INFORMATION (0x0400) PROCESS_QUERY_LIMITED_INFORMATION (0x1000) - (This comes as a result of needing PROCESS_QUERY_INFORMATION) PROCESS_VM_OPERATION (0x0008) PROCESS_VM_WRITE (0x0010) PROCESS_VM_READ (0x0020)\n", 124 | "'''\n", 125 | ").show(1,False)" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [] 134 | } 135 | ], 136 | "metadata": { 137 | "kernelspec": { 138 | "display_name": "PySpark_Python3", 139 | "language": "python", 140 | "name": "pyspark3" 141 | }, 142 | "language_info": { 143 | "codemirror_mode": { 144 | "name": "ipython", 145 | "version": 3 146 | }, 147 | "file_extension": ".py", 148 | "mimetype": "text/x-python", 149 | "name": "python", 150 | "nbconvert_exporter": "python", 151 | "pygments_lexer": "ipython3", 152 | "version": "3.7.3" 153 | } 154 | }, 155 | "nbformat": 4, 156 | "nbformat_minor": 4 157 | } 158 | -------------------------------------------------------------------------------- /Detection_Notebooks/DLL_Injection/DLL_Injection_CRT_Transformed.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 20, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from pyspark.sql import SparkSession" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 21, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "spark = SparkSession.builder \\\n", 19 | " .appName(\"HELK Reader\") \\\n", 20 | " .master(\"spark://helk-spark-master:7077\") \\\n", 21 | " .enableHiveSupport() \\\n", 22 | " .getOrCreate()" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 22, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "es_reader = (spark.read\n", 32 | " .format(\"org.elasticsearch.spark.sql\")\n", 33 | " .option(\"inferSchema\", \"true\")\n", 34 | " .option(\"es.read.field.as.array.include\", \"tags\")\n", 35 | " .option(\"es.nodes\",\"helk-elasticsearch:9200\")\n", 36 | " .option(\"es.net.http.auth.user\",\"elastic\")\n", 37 | ")" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 23, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "sysmon_df = es_reader.load(\"logs-endpoint-winevent-sysmon-*/\")" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 24, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "sysmon_df.createOrReplaceTempView(\"sysmon_events\")" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 28, 61 | "metadata": {}, 62 | "outputs": [ 63 | { 64 | "name": "stdout", 65 | "output_type": "stream", 66 | "text": [ 67 | "+------------------+--------------+----------------------+----------+-------------------+-------------+\n", 68 | "|host_name |process_name |process_granted_access|process_id|process_target_name|thread_new_id|\n", 69 | "+------------------+--------------+----------------------+----------+-------------------+-------------+\n", 70 | "|hr001.shire.com |powershell.exe|2047999 |5452 |notepad.exe |7940 |\n", 71 | "|win10.marvel.local|injectdll.exe |2097151 |9028 |notepad.exe |2216 |\n", 72 | "|win10.marvel.local|injectdll.exe |2097151 |8220 |notepad.exe |7524 |\n", 73 | "|win10.marvel.local|injectdll.exe |2097151 |9204 |notepad.exe |7972 |\n", 74 | "|win10.marvel.local|injectdll.exe |2097151 |6440 |notepad.exe |8492 |\n", 75 | "|win10.marvel.local|injectdll.exe |2097151 |868 |notepad.exe |8580 |\n", 76 | "|win10.marvel.local|injectdll.exe |2097151 |2556 |notepad.exe |3004 |\n", 77 | "|win10.marvel.local|injectdll.exe |2097151 |7240 |notepad.exe |6260 |\n", 78 | "|win10.marvel.local|injectdll.exe |2097151 |8260 |notepad.exe |8852 |\n", 79 | "+------------------+--------------+----------------------+----------+-------------------+-------------+\n", 80 | "\n" 81 | ] 82 | } 83 | ], 84 | "source": [ 85 | "DLL_Injection_EID_8_10 = spark.sql(\n", 86 | "'''\n", 87 | "SELECT \n", 88 | " a.host_name,\n", 89 | " a.process_name,\n", 90 | " a.process_granted_access,\n", 91 | " a.process_id, \n", 92 | " a.process_target_name,\n", 93 | " c.thread_new_id\n", 94 | "FROM sysmon_events c\n", 95 | "JOIN sysmon_events a\n", 96 | " ON a.process_guid = c.process_guid\n", 97 | " AND a.event_id = 10\n", 98 | " AND (a.process_granted_access & 5170) == 5170 -- 5170 is decimal for (0x143A). The minimal privileges you need to obtain a handle in the target process PROCESS_CREATE_THREAD (0x0002) PROCESS_QUERY_INFORMATION (0x0400) PROCESS_QUERY_LIMITED_INFORMATION (0x1000) - (This comes as a result of needing PROCESS_QUERY_INFORMATION) PROCESS_VM_OPERATION (0x0008) PROCESS_VM_WRITE (0x0010) PROCESS_VM_READ (0x0020)\n", 99 | "WHERE\n", 100 | " c.event_id = 8\n", 101 | " AND c.thread_start_function = \"LoadLibraryA\" OR c.thread_start_function = \"LoadLibraryW\"\n", 102 | "'''\n", 103 | ").show(100,False)" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [] 112 | } 113 | ], 114 | "metadata": { 115 | "kernelspec": { 116 | "display_name": "PySpark_Python3", 117 | "language": "python", 118 | "name": "pyspark3" 119 | }, 120 | "language_info": { 121 | "codemirror_mode": { 122 | "name": "ipython", 123 | "version": 3 124 | }, 125 | "file_extension": ".py", 126 | "mimetype": "text/x-python", 127 | "name": "python", 128 | "nbconvert_exporter": "python", 129 | "pygments_lexer": "ipython3", 130 | "version": "3.7.3" 131 | } 132 | }, 133 | "nbformat": 4, 134 | "nbformat_minor": 4 135 | } 136 | -------------------------------------------------------------------------------- /Detection_Notebooks/DLL_Injection/DLL_Injection_RTL_Raw.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from openhunt.logparser import winlogbeat\n", 10 | "from pyspark.sql import SparkSession\n", 11 | "from pyspark.sql.functions import *" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 2, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "win = winlogbeat()\n", 21 | "spark = SparkSession.builder.appName(\"Process\").config(\"spark.sql.caseSensitive\", \"True\").getOrCreate()" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 3, 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "name": "stdout", 31 | "output_type": "stream", 32 | "text": [ 33 | "[+] Processing a Spark DataFrame..\n", 34 | "[+] Reading Mordor file..\n", 35 | "[+] Processing Data from Winlogbeat version 7..\n", 36 | "[+] DataFrame Returned !\n" 37 | ] 38 | } 39 | ], 40 | "source": [ 41 | "process_injection = win.extract_nested_fields(\"dll_injection_2020-01-12160439.json\",spark)" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 4, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "process_injection.createOrReplaceTempView(\"process_injection\")" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 5, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "DLL_Injection = spark.sql(\n", 60 | "'''\n", 61 | "SELECT \n", 62 | " b.computer_name,\n", 63 | " b.SourceImage,\n", 64 | " ltrim('0x', b.GrantedAccess) as granted_access,\n", 65 | " b.TargetImage,\n", 66 | " b.SourceProcessId,\n", 67 | " b.SourceProcessGUID,\n", 68 | " c.NewThreadId,\n", 69 | " b.TargetProcessId,\n", 70 | " b.TargetImage,\n", 71 | " c.StartFunction\n", 72 | "FROM process_injection c\n", 73 | "JOIN process_injection b\n", 74 | " ON c.SourceProcessGuid = b.SourceProcessGUID\n", 75 | " AND b.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 76 | " AND b.event_id = 10\n", 77 | "WHERE c.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 78 | " AND c.event_id = 8\n", 79 | " AND c.StartFunction = \"LoadLibraryA\" OR c.StartFunction = \"LoadLibraryW\"\n", 80 | "'''\n", 81 | ")\n" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 6, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "df = DLL_Injection.select(\"computer_name\", conv(DLL_Injection.granted_access, 16, 10).alias(\"granted_access\"), \"SourceImage\", \"SourceProcessGUID\", \"NewThreadId\", \"TargetProcessId\", \"TargetImage\")" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 7, 96 | "metadata": {}, 97 | "outputs": [], 98 | "source": [ 99 | "df.createOrReplaceTempView(\"df\")" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 8, 105 | "metadata": {}, 106 | "outputs": [ 107 | { 108 | "name": "stdout", 109 | "output_type": "stream", 110 | "text": [ 111 | "+------------------+--------------+-------------------------------------------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 112 | "|computer_name |granted_access|SourceImage |SourceProcessGUID |NewThreadId|TargetProcessId|TargetImage |\n", 113 | "+------------------+--------------+-------------------------------------------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 114 | "|win10.marvel.local|2097151 |C:\\Users\\thor\\Downloads\\injection-master\\injection-master\\InjectDLL\\x64\\Debug\\InjectDLL.exe|{9d556bd4-b423-5e1b-0000-00104e060d01}|3004 |8288 |C:\\WINDOWS\\system32\\notepad.exe|\n", 115 | "+------------------+--------------+-------------------------------------------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 116 | "\n" 117 | ] 118 | } 119 | ], 120 | "source": [ 121 | "eid_8_10_minimal_privileges = spark.sql(\n", 122 | "'''\n", 123 | "SELECT * FROM df WHERE ((INT(granted_access) & 40) == 40) -- 40 is decimal for 0x0028. The minimal privileges you need to obtain a handle are: PROCESS_VM_OPERATION (0x0008) PROCESS_VM_WRITE (0x0020)\n", 124 | "'''\n", 125 | ").show(1,False)" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [] 134 | } 135 | ], 136 | "metadata": { 137 | "kernelspec": { 138 | "display_name": "PySpark_Python3", 139 | "language": "python", 140 | "name": "pyspark3" 141 | }, 142 | "language_info": { 143 | "codemirror_mode": { 144 | "name": "ipython", 145 | "version": 3 146 | }, 147 | "file_extension": ".py", 148 | "mimetype": "text/x-python", 149 | "name": "python", 150 | "nbconvert_exporter": "python", 151 | "pygments_lexer": "ipython3", 152 | "version": "3.7.3" 153 | } 154 | }, 155 | "nbformat": 4, 156 | "nbformat_minor": 4 157 | } 158 | -------------------------------------------------------------------------------- /Detection_Notebooks/DLL_Injection/DLL_Injection_RTL_Transformed.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 20, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from pyspark.sql import SparkSession" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 21, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "spark = SparkSession.builder \\\n", 19 | " .appName(\"HELK Reader\") \\\n", 20 | " .master(\"spark://helk-spark-master:7077\") \\\n", 21 | " .enableHiveSupport() \\\n", 22 | " .getOrCreate()" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 22, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "es_reader = (spark.read\n", 32 | " .format(\"org.elasticsearch.spark.sql\")\n", 33 | " .option(\"inferSchema\", \"true\")\n", 34 | " .option(\"es.read.field.as.array.include\", \"tags\")\n", 35 | " .option(\"es.nodes\",\"helk-elasticsearch:9200\")\n", 36 | " .option(\"es.net.http.auth.user\",\"elastic\")\n", 37 | ")" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 23, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "sysmon_df = es_reader.load(\"logs-endpoint-winevent-sysmon-*/\")" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 24, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "sysmon_df.createOrReplaceTempView(\"sysmon_events\")" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 28, 61 | "metadata": {}, 62 | "outputs": [ 63 | { 64 | "name": "stdout", 65 | "output_type": "stream", 66 | "text": [ 67 | "+------------------+--------------+----------------------+----------+-------------------+-------------+\n", 68 | "|host_name |process_name |process_granted_access|process_id|process_target_name|thread_new_id|\n", 69 | "+------------------+--------------+----------------------+----------+-------------------+-------------+\n", 70 | "|hr001.shire.com |powershell.exe|2047999 |5452 |notepad.exe |7940 |\n", 71 | "|win10.marvel.local|injectdll.exe |2097151 |9028 |notepad.exe |2216 |\n", 72 | "|win10.marvel.local|injectdll.exe |2097151 |8220 |notepad.exe |7524 |\n", 73 | "|win10.marvel.local|injectdll.exe |2097151 |9204 |notepad.exe |7972 |\n", 74 | "|win10.marvel.local|injectdll.exe |2097151 |6440 |notepad.exe |8492 |\n", 75 | "|win10.marvel.local|injectdll.exe |2097151 |868 |notepad.exe |8580 |\n", 76 | "|win10.marvel.local|injectdll.exe |2097151 |2556 |notepad.exe |3004 |\n", 77 | "|win10.marvel.local|injectdll.exe |2097151 |7240 |notepad.exe |6260 |\n", 78 | "|win10.marvel.local|injectdll.exe |2097151 |8260 |notepad.exe |8852 |\n", 79 | "+------------------+--------------+----------------------+----------+-------------------+-------------+\n", 80 | "\n" 81 | ] 82 | } 83 | ], 84 | "source": [ 85 | "DLL_Injection_EID_8_10 = spark.sql(\n", 86 | "'''\n", 87 | "SELECT \n", 88 | " a.host_name,\n", 89 | " a.process_name,\n", 90 | " a.process_granted_access,\n", 91 | " a.process_id, \n", 92 | " a.process_target_name,\n", 93 | " c.thread_new_id\n", 94 | "FROM sysmon_events c\n", 95 | "JOIN sysmon_events a\n", 96 | " ON a.process_guid = c.process_guid\n", 97 | " AND a.event_id = 10\n", 98 | " AND (a.process_granted_access & 40) == 40 -- 40 is decimal for 0x0028. The minimal privileges you need to obtain a handle are: PROCESS_VM_OPERATION (0x0008) PROCESS_VM_WRITE (0x0020)\n", 99 | "WHERE\n", 100 | " c.event_id = 8\n", 101 | " AND c.thread_start_function = \"LoadLibraryA\" OR c.thread_start_function = \"LoadLibraryW\"\n", 102 | "'''\n", 103 | ").show(100,False)" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [] 112 | } 113 | ], 114 | "metadata": { 115 | "kernelspec": { 116 | "display_name": "PySpark_Python3", 117 | "language": "python", 118 | "name": "pyspark3" 119 | }, 120 | "language_info": { 121 | "codemirror_mode": { 122 | "name": "ipython", 123 | "version": 3 124 | }, 125 | "file_extension": ".py", 126 | "mimetype": "text/x-python", 127 | "name": "python", 128 | "nbconvert_exporter": "python", 129 | "pygments_lexer": "ipython3", 130 | "version": "3.7.3" 131 | } 132 | }, 133 | "nbformat": 4, 134 | "nbformat_minor": 4 135 | } 136 | -------------------------------------------------------------------------------- /Detection_Notebooks/DLL_Injection/DLL_Injection_Raw.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from openhunt.logparser import winlogbeat\n", 10 | "from pyspark.sql import SparkSession\n", 11 | "from pyspark.sql.functions import *" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 2, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "win = winlogbeat()\n", 21 | "spark = SparkSession.builder.appName(\"Process\").config(\"spark.sql.caseSensitive\", \"True\").getOrCreate()" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 3, 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "name": "stdout", 31 | "output_type": "stream", 32 | "text": [ 33 | "[+] Processing a Spark DataFrame..\n", 34 | "[+] Reading Mordor file..\n", 35 | "[+] Processing Data from Winlogbeat version 7..\n", 36 | "[+] DataFrame Returned !\n" 37 | ] 38 | } 39 | ], 40 | "source": [ 41 | "process_injection = win.extract_nested_fields(\"dll_injection_2020-01-12160439.json\",spark)" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 4, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "process_injection.createOrReplaceTempView(\"process_injection\")" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 5, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "DLL_Injection = spark.sql(\n", 60 | "'''\n", 61 | "SELECT \n", 62 | " b.computer_name,\n", 63 | " b.SourceImage,\n", 64 | " ltrim('0x', b.GrantedAccess) as granted_access,\n", 65 | " b.TargetImage,\n", 66 | " b.SourceProcessId,\n", 67 | " b.SourceProcessGUID,\n", 68 | " c.NewThreadId,\n", 69 | " b.TargetProcessId,\n", 70 | " b.TargetImage,\n", 71 | " c.StartFunction\n", 72 | "FROM process_injection c\n", 73 | "JOIN process_injection b\n", 74 | " ON c.SourceProcessGuid = b.SourceProcessGUID\n", 75 | " AND b.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 76 | " AND b.event_id = 10\n", 77 | "WHERE c.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 78 | " AND c.event_id = 8\n", 79 | " AND c.StartFunction = \"LoadLibraryA\" OR c.StartFunction = \"LoadLibraryW\"\n", 80 | "'''\n", 81 | ")\n" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 6, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "df = DLL_Injection.select(\"computer_name\", conv(DLL_Injection.granted_access, 16, 10).alias(\"granted_access\"), \"SourceImage\", \"SourceProcessGUID\", \"NewThreadId\", \"TargetProcessId\", \"TargetImage\")" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 7, 96 | "metadata": {}, 97 | "outputs": [], 98 | "source": [ 99 | "df.createOrReplaceTempView(\"df\")" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 8, 105 | "metadata": {}, 106 | "outputs": [ 107 | { 108 | "name": "stdout", 109 | "output_type": "stream", 110 | "text": [ 111 | "+------------------+--------------+-------------------------------------------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 112 | "|computer_name |granted_access|SourceImage |SourceProcessGUID |NewThreadId|TargetProcessId|TargetImage |\n", 113 | "+------------------+--------------+-------------------------------------------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 114 | "|win10.marvel.local|2097151 |C:\\Users\\thor\\Downloads\\injection-master\\injection-master\\InjectDLL\\x64\\Debug\\InjectDLL.exe|{9d556bd4-b423-5e1b-0000-00104e060d01}|3004 |8288 |C:\\WINDOWS\\system32\\notepad.exe|\n", 115 | "+------------------+--------------+-------------------------------------------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 116 | "\n" 117 | ] 118 | } 119 | ], 120 | "source": [ 121 | "eid_8_10_minimal_privileges = spark.sql(\n", 122 | "'''\n", 123 | "SELECT * FROM df WHERE ((INT(granted_access) & 40) == 40) -- 40 is decimal for 0x0028. The minimal privileges you need to access process handle\n", 124 | "'''\n", 125 | ").show(1,False)" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [] 134 | } 135 | ], 136 | "metadata": { 137 | "kernelspec": { 138 | "display_name": "PySpark_Python3", 139 | "language": "python", 140 | "name": "pyspark3" 141 | }, 142 | "language_info": { 143 | "codemirror_mode": { 144 | "name": "ipython", 145 | "version": 3 146 | }, 147 | "file_extension": ".py", 148 | "mimetype": "text/x-python", 149 | "name": "python", 150 | "nbconvert_exporter": "python", 151 | "pygments_lexer": "ipython3", 152 | "version": "3.7.3" 153 | } 154 | }, 155 | "nbformat": 4, 156 | "nbformat_minor": 4 157 | } 158 | -------------------------------------------------------------------------------- /Detection_Notebooks/DLL_Injection/DLL_Injection_Transformed.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 20, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from pyspark.sql import SparkSession" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 21, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "spark = SparkSession.builder \\\n", 19 | " .appName(\"HELK Reader\") \\\n", 20 | " .master(\"spark://helk-spark-master:7077\") \\\n", 21 | " .enableHiveSupport() \\\n", 22 | " .getOrCreate()" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 22, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "es_reader = (spark.read\n", 32 | " .format(\"org.elasticsearch.spark.sql\")\n", 33 | " .option(\"inferSchema\", \"true\")\n", 34 | " .option(\"es.read.field.as.array.include\", \"tags\")\n", 35 | " .option(\"es.nodes\",\"helk-elasticsearch:9200\")\n", 36 | " .option(\"es.net.http.auth.user\",\"elastic\")\n", 37 | ")" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 23, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "sysmon_df = es_reader.load(\"logs-endpoint-winevent-sysmon-*/\")" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 24, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "sysmon_df.createOrReplaceTempView(\"sysmon_events\")" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 28, 61 | "metadata": {}, 62 | "outputs": [ 63 | { 64 | "name": "stdout", 65 | "output_type": "stream", 66 | "text": [ 67 | "+------------------+--------------+----------------------+----------+-------------------+-------------+\n", 68 | "|host_name |process_name |process_granted_access|process_id|process_target_name|thread_new_id|\n", 69 | "+------------------+--------------+----------------------+----------+-------------------+-------------+\n", 70 | "|hr001.shire.com |powershell.exe|2047999 |5452 |notepad.exe |7940 |\n", 71 | "|win10.marvel.local|injectdll.exe |2097151 |9028 |notepad.exe |2216 |\n", 72 | "|win10.marvel.local|injectdll.exe |2097151 |8220 |notepad.exe |7524 |\n", 73 | "|win10.marvel.local|injectdll.exe |2097151 |9204 |notepad.exe |7972 |\n", 74 | "|win10.marvel.local|injectdll.exe |2097151 |6440 |notepad.exe |8492 |\n", 75 | "|win10.marvel.local|injectdll.exe |2097151 |868 |notepad.exe |8580 |\n", 76 | "|win10.marvel.local|injectdll.exe |2097151 |2556 |notepad.exe |3004 |\n", 77 | "|win10.marvel.local|injectdll.exe |2097151 |7240 |notepad.exe |6260 |\n", 78 | "|win10.marvel.local|injectdll.exe |2097151 |8260 |notepad.exe |8852 |\n", 79 | "+------------------+--------------+----------------------+----------+-------------------+-------------+\n", 80 | "\n" 81 | ] 82 | } 83 | ], 84 | "source": [ 85 | "DLL_Injection_EID_8_10 = spark.sql(\n", 86 | "'''\n", 87 | "SELECT \n", 88 | " a.host_name,\n", 89 | " a.process_name,\n", 90 | " a.process_granted_access,\n", 91 | " a.process_id, \n", 92 | " a.process_target_name,\n", 93 | " c.thread_new_id\n", 94 | "FROM sysmon_events c\n", 95 | "JOIN sysmon_events a\n", 96 | " ON a.process_guid = c.process_guid\n", 97 | " AND a.event_id = 10\n", 98 | " AND (a.process_granted_access & 40) == 40 -- 40 is decimal for 0x0028. The minimal privileges you need to access process handle\n", 99 | "WHERE\n", 100 | " c.event_id = 8\n", 101 | " AND c.thread_start_function = \"LoadLibraryA\" OR c.thread_start_function = \"LoadLibraryW\"\n", 102 | "'''\n", 103 | ").show(100,False)" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [] 112 | } 113 | ], 114 | "metadata": { 115 | "kernelspec": { 116 | "display_name": "PySpark_Python3", 117 | "language": "python", 118 | "name": "pyspark3" 119 | }, 120 | "language_info": { 121 | "codemirror_mode": { 122 | "name": "ipython", 123 | "version": 3 124 | }, 125 | "file_extension": ".py", 126 | "mimetype": "text/x-python", 127 | "name": "python", 128 | "nbconvert_exporter": "python", 129 | "pygments_lexer": "ipython3", 130 | "version": "3.7.3" 131 | } 132 | }, 133 | "nbformat": 4, 134 | "nbformat_minor": 4 135 | } 136 | -------------------------------------------------------------------------------- /Detection_Notebooks/Hook_Injection/Hook_Injection.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsecurity101/Detecting-Process-Injection-Techniques/3b77a4f1b374cd950a42a4fd680a32277effa61a/Detection_Notebooks/Hook_Injection/Hook_Injection.tar.gz -------------------------------------------------------------------------------- /Detection_Notebooks/Hook_Injection/Hook_Injection_Raw.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from openhunt.logparser import winlogbeat\n", 10 | "from pyspark.sql import SparkSession\n", 11 | "from pyspark.sql.functions import *" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 2, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "win = winlogbeat()\n", 21 | "spark = SparkSession.builder.appName(\"Process\").config(\"spark.sql.caseSensitive\", \"True\").getOrCreate()" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 3, 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "name": "stdout", 31 | "output_type": "stream", 32 | "text": [ 33 | "[+] Processing a Spark DataFrame..\n", 34 | "[+] Reading Mordor file..\n", 35 | "[+] Processing Data from Winlogbeat version 7..\n", 36 | "[+] DataFrame Returned !\n" 37 | ] 38 | } 39 | ], 40 | "source": [ 41 | "hook_injection = win.extract_nested_fields(\"hook_injection_2020-01-13170701.json\",spark)" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 4, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "hook_injection.createOrReplaceTempView(\"hook_injection\")" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 5, 56 | "metadata": {}, 57 | "outputs": [ 58 | { 59 | "name": "stdout", 60 | "output_type": "stream", 61 | "text": [ 62 | "+------------------+-----------+--------------------------------------+-------------------------------+-------+--------------+\n", 63 | "|computer_name |User |ParentImage |TargetImage |LogonId|granted_access|\n", 64 | "+------------------+-----------+--------------------------------------+-------------------------------+-------+--------------+\n", 65 | "|win10.marvel.local|MARVEL\\thor|C:\\Users\\thor\\Downloads\\InjectProc.exe|C:\\Windows\\System32\\notepad.exe|0xdcff8|1fffff |\n", 66 | "+------------------+-----------+--------------------------------------+-------------------------------+-------+--------------+\n", 67 | "\n" 68 | ] 69 | } 70 | ], 71 | "source": [ 72 | "Hook_Injection = spark.sql(\n", 73 | "'''\n", 74 | "SELECT \n", 75 | " b.computer_name, \n", 76 | " b.User,\n", 77 | " b.ParentImage,\n", 78 | " d.TargetImage,\n", 79 | " b.LogonId,\n", 80 | " ltrim('0x', d.GrantedAccess) as granted_access\n", 81 | "FROM hook_injection b \n", 82 | "JOIN hook_injection d\n", 83 | " ON b.ProcessGuid = d.TargetProcessGUID\n", 84 | " AND d.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 85 | " AND d.event_id = 10\n", 86 | " AND b.ParentProcessGuid = d.SourceProcessGUID\n", 87 | " AND b.Image = d.TargetImage\n", 88 | "JOIN hook_injection e\n", 89 | " ON e.ProcessGuid = b.ParentProcessGuid\n", 90 | " AND e.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 91 | " AND e.event_id = 5\n", 92 | " AND e.Image = d.SourceImage\n", 93 | " AND b.ParentImage = e.Image\n", 94 | "JOIN hook_injection f\n", 95 | " ON f.ProcessGuid = b.ParentProcessGuid\n", 96 | " AND f.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 97 | " AND f.event_id = 7\n", 98 | " AND f.Image = b.ParentImage\n", 99 | " AND f.Image = f.ImageLoaded\n", 100 | "WHERE b.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 101 | " AND b.event_id = 1\n", 102 | "'''\n", 103 | ").show(1,False)" 104 | ] 105 | } 106 | ], 107 | "metadata": { 108 | "kernelspec": { 109 | "display_name": "PySpark_Python3", 110 | "language": "python", 111 | "name": "pyspark3" 112 | }, 113 | "language_info": { 114 | "codemirror_mode": { 115 | "name": "ipython", 116 | "version": 3 117 | }, 118 | "file_extension": ".py", 119 | "mimetype": "text/x-python", 120 | "name": "python", 121 | "nbconvert_exporter": "python", 122 | "pygments_lexer": "ipython3", 123 | "version": "3.7.3" 124 | } 125 | }, 126 | "nbformat": 4, 127 | "nbformat_minor": 4 128 | } 129 | -------------------------------------------------------------------------------- /Detection_Notebooks/Hook_Injection/Hook_Injection_Transformed.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 29, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from pyspark.sql import SparkSession" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 30, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "spark = SparkSession.builder \\\n", 19 | " .appName(\"HELK Reader\") \\\n", 20 | " .master(\"spark://helk-spark-master:7077\") \\\n", 21 | " .enableHiveSupport() \\\n", 22 | " .getOrCreate()" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 31, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "es_reader = (spark.read\n", 32 | " .format(\"org.elasticsearch.spark.sql\")\n", 33 | " .option(\"inferSchema\", \"true\")\n", 34 | " .option(\"es.read.field.as.array.include\", \"tags\")\n", 35 | " .option(\"es.nodes\",\"helk-elasticsearch:9200\")\n", 36 | " .option(\"es.net.http.auth.user\",\"elastic\")\n", 37 | ")" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 32, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "security_df = es_reader.load(\"logs-endpoint-winevent-security-*/\")" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 33, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "security_df.createOrReplaceTempView(\"security_events\")" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 34, 61 | "metadata": {}, 62 | "outputs": [], 63 | "source": [ 64 | "sysmon_df = es_reader.load(\"logs-endpoint-winevent-sysmon-*/\")" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 35, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "sysmon_df.createOrReplaceTempView(\"sysmon_events\")" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 43, 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "name": "stdout", 83 | "output_type": "stream", 84 | "text": [ 85 | "+------------------+---------+--------------------+-------------------+--------------------+----------------------+\n", 86 | "|host_name |user_name|process_parent_name |process_target_name|Sysmon_EID_1_LogonId|process_granted_access|\n", 87 | "+------------------+---------+--------------------+-------------------+--------------------+----------------------+\n", 88 | "|win10.marvel.local|thor |processhollowing.exe|cmd.exe |9340634 |2097151 |\n", 89 | "|win10.marvel.local|thor |processhollowing.exe|svchost.exe |9340634 |2097151 |\n", 90 | "|win10.marvel.local|thor |injectproc.exe |cmd.exe |537356 |2097151 |\n", 91 | "+------------------+---------+--------------------+-------------------+--------------------+----------------------+\n", 92 | "\n" 93 | ] 94 | } 95 | ], 96 | "source": [ 97 | "hook_and_hollowing = spark.sql(\n", 98 | "'''\n", 99 | "SELECT \n", 100 | " c.host_name, \n", 101 | " c.user_name,\n", 102 | " c.process_parent_name,\n", 103 | " d.process_target_name,\n", 104 | " c.user_logon_id AS Sysmon_EID_1_LogonId,\n", 105 | " d.process_granted_access\n", 106 | "FROM security_events b\n", 107 | "JOIN sysmon_events c\n", 108 | " ON c.process_name = b.process_name\n", 109 | " AND c.event_id = 1\n", 110 | " AND c.user_name = b.user_name\n", 111 | "JOIN sysmon_events d\n", 112 | " ON c.process_guid = d.process_target_guid\n", 113 | " AND d.event_id = 10\n", 114 | " AND d.process_granted_access = \"2097151\" -- Assuming they are asking for full privileges. Was hard to narrow down the minimum rights needed to perform. As the main API being utilized is SetWindowsHookEx\n", 115 | " AND c.process_parent_guid = d.process_guid\n", 116 | " AND c.process_name = d.process_target_name\n", 117 | " AND (NOT (c.process_parent_name = \"msbuild.exe\" AND d.process_target_name = \"cmd.exe\")) -- Blind spot + Assumption\n", 118 | "JOIN sysmon_events e\n", 119 | " ON e.process_guid = c.process_parent_guid\n", 120 | " AND e.event_id = 5\n", 121 | " AND e.process_name = d.process_name\n", 122 | " AND c.process_parent_name = e.process_name \n", 123 | "JOIN sysmon_events f\n", 124 | " ON f.process_guid = c.process_parent_guid\n", 125 | " AND f.event_id = 7\n", 126 | " AND f.process_path = c.process_parent_path\n", 127 | " AND f.process_path = f.module_loaded\n", 128 | " AND f.signed = \"false\" -- Trivial for adversary to bypass. Here for extra context. \n", 129 | "WHERE \n", 130 | " b.event_id = 4688\n", 131 | "'''\n", 132 | ").show(10,False)" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": 44, 138 | "metadata": {}, 139 | "outputs": [ 140 | { 141 | "name": "stdout", 142 | "output_type": "stream", 143 | "text": [ 144 | "+------------------+--------------------+-------------------+----------------------+------------------+\n", 145 | "| host_name| process_parent_name|process_target_name|process_granted_access|user_reporter_name|\n", 146 | "+------------------+--------------------+-------------------+----------------------+------------------+\n", 147 | "|win10.marvel.local| injectproc.exe| cmd.exe| 2097151| SYSTEM|\n", 148 | "|win10.marvel.local| injectproc.exe| notepad.exe| 2097151| SYSTEM|\n", 149 | "|win10.marvel.local|processhollowing.exe| svchost.exe| 2097151| SYSTEM|\n", 150 | "|win10.marvel.local| injectproc.exe| notepad.exe| 2097151| SYSTEM|\n", 151 | "|win10.marvel.local| cmd.exe| powershell.exe| 2097151| SYSTEM|\n", 152 | "|win10.marvel.local| cmd.exe| powershell.exe| 2097151| SYSTEM|\n", 153 | "+------------------+--------------------+-------------------+----------------------+------------------+\n", 154 | "\n" 155 | ] 156 | } 157 | ], 158 | "source": [ 159 | "Hook_Injection = spark.sql(\n", 160 | "'''\n", 161 | "SELECT \n", 162 | " b.host_name,\n", 163 | " b.process_parent_name,\n", 164 | " a.process_target_name,\n", 165 | " a.process_granted_access,\n", 166 | " a.user_reporter_name\n", 167 | "FROM sysmon_events b\n", 168 | "JOIN sysmon_events a\n", 169 | " ON a.process_target_guid = b.process_guid\n", 170 | " AND a.event_id = 10\n", 171 | " AND a.process_granted_access = \"2097151\" -- Assuming they are asking for full privileges. Was hard to narrow down the minimum rights needed to perform. As the main API being utilized is SetWindowsHookEx \n", 172 | " AND b.process_parent_name = a.process_name\n", 173 | " AND a.process_name != b.process_name\n", 174 | "JOIN sysmon_events c\n", 175 | " ON b.process_guid = c.process_guid\n", 176 | " AND c.event_id = 13\n", 177 | " AND c.process_guid = a.process_target_guid\n", 178 | " AND c.process_name = a.process_target_name \n", 179 | " AND (substring_index(c.registry_key_path, '\\\\\\\\', -1)) = b.process_name\n", 180 | "JOIN sysmon_events d\n", 181 | " ON d.process_guid = a.process_target_guid\n", 182 | " AND d.event_id = 7\n", 183 | " AND d.module_loaded = a.process_target_path\n", 184 | " AND LOWER(d.OriginalFileName) = (substring_index(c.registry_key_path, '\\\\\\\\', -1))\n", 185 | " AND d.OriginalFileName = b.OriginalFileName\n", 186 | "WHERE\n", 187 | " b.event_id = 1\n", 188 | " AND b.process_name = LOWER(b.OriginalFileName)\n", 189 | " AND (NOT (b.process_name = \"rundll32.exe\" AND b.process_parent_name = \"svchost.exe\")) -- Blind spot + Assumption\n", 190 | " AND (NOT (b.process_name = \"notepad.exe\" AND b.process_parent_name = \"explorer.exe\")) -- Blind spot + Assumption\n", 191 | " AND (NOT (b.process_name = \"devenv.exe\" AND b.process_parent_name = \"explorer.exe\")) -- Blind spot + Assumption\n", 192 | " AND (NOT (b.process_name = \"cmd.exe\" AND b.process_parent_name = \"explorer.exe\")) -- Blind spot + Assumption\n", 193 | "'''\n", 194 | ").show()" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": null, 200 | "metadata": {}, 201 | "outputs": [], 202 | "source": [ 203 | "# https://github.com/secrary/InjectProc" 204 | ] 205 | } 206 | ], 207 | "metadata": { 208 | "kernelspec": { 209 | "display_name": "PySpark_Python3", 210 | "language": "python", 211 | "name": "pyspark3" 212 | }, 213 | "language_info": { 214 | "codemirror_mode": { 215 | "name": "ipython", 216 | "version": 3 217 | }, 218 | "file_extension": ".py", 219 | "mimetype": "text/x-python", 220 | "name": "python", 221 | "nbconvert_exporter": "python", 222 | "pygments_lexer": "ipython3", 223 | "version": "3.7.3" 224 | } 225 | }, 226 | "nbformat": 4, 227 | "nbformat_minor": 4 228 | } 229 | -------------------------------------------------------------------------------- /Detection_Notebooks/Process_Hollow/Process_Hollowing.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsecurity101/Detecting-Process-Injection-Techniques/3b77a4f1b374cd950a42a4fd680a32277effa61a/Detection_Notebooks/Process_Hollow/Process_Hollowing.tar.gz -------------------------------------------------------------------------------- /Detection_Notebooks/Process_Hollow/Process_Hollowing_Raw.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from openhunt.logparser import winlogbeat\n", 10 | "from pyspark.sql import SparkSession\n", 11 | "from pyspark.sql.functions import *" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 2, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "win = winlogbeat()\n", 21 | "spark = SparkSession.builder.appName(\"Process\").config(\"spark.sql.caseSensitive\", \"True\").getOrCreate()" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 3, 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "name": "stdout", 31 | "output_type": "stream", 32 | "text": [ 33 | "[+] Processing a Spark DataFrame..\n", 34 | "[+] Reading Mordor file..\n", 35 | "[+] Processing Data from Winlogbeat version 7..\n", 36 | "[+] DataFrame Returned !\n" 37 | ] 38 | } 39 | ], 40 | "source": [ 41 | "process_hollowing = win.extract_nested_fields(\"process_hollowing_2019-10-17111939.json\",spark)" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 4, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "process_hollowing.createOrReplaceTempView(\"process_hollowing\")" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 5, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "ProcessHollowing = spark.sql(\n", 60 | "'''\n", 61 | "SELECT \n", 62 | " c.computer_name, \n", 63 | " c.User,\n", 64 | " c.ParentImage,\n", 65 | " d.TargetImage,\n", 66 | " c.LogonId,\n", 67 | " ltrim('0x', d.GrantedAccess) as granted_access\n", 68 | "FROM process_hollowing b \n", 69 | "JOIN process_hollowing c\n", 70 | " ON c.Image = b.NewProcessName\n", 71 | " AND c.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 72 | " AND c.event_id = 1\n", 73 | " AND b.SubjectUserName = (substring_index(c.User, '\\\\\\\\', -1))\n", 74 | "JOIN process_hollowing d\n", 75 | " ON c.ProcessGuid = d.TargetProcessGUID\n", 76 | " AND d.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 77 | " AND d.event_id = 10\n", 78 | " AND c.ParentProcessGuid = d.SourceProcessGUID\n", 79 | " AND c.Image = d.TargetImage\n", 80 | "JOIN process_hollowing f\n", 81 | " ON f.ProcessGuid = c.ParentProcessGuid\n", 82 | " AND f.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 83 | " AND f.event_id = 7\n", 84 | " AND f.Image = c.ParentImage\n", 85 | " AND f.Image = f.ImageLoaded\n", 86 | "WHERE b.channel = \"Security\"\n", 87 | " AND b.event_id = 4688\n", 88 | "'''\n", 89 | ")" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 6, 95 | "metadata": {}, 96 | "outputs": [], 97 | "source": [ 98 | "\n", 99 | "df = ProcessHollowing.select(\"computer_name\", conv(ProcessHollowing.granted_access, 16, 10).alias(\"granted_access\"), \"User\", \"ParentImage\", \"TargetImage\", \"LogonId\")" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 7, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "df.createOrReplaceTempView(\"df\")" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 8, 114 | "metadata": {}, 115 | "outputs": [ 116 | { 117 | "name": "stdout", 118 | "output_type": "stream", 119 | "text": [ 120 | "+------------------+--------------+-----------+----------------------------------------+-------------------------------+--------+\n", 121 | "|computer_name |granted_access|User |ParentImage |TargetImage |LogonId |\n", 122 | "+------------------+--------------+-----------+----------------------------------------+-------------------------------+--------+\n", 123 | "|win10.marvel.local|2097151 |MARVEL\\thor|C:\\ProcessHollowing\\ProcessHollowing.exe|C:\\Windows\\SysWOW64\\svchost.exe|0x8e86da|\n", 124 | "+------------------+--------------+-----------+----------------------------------------+-------------------------------+--------+\n", 125 | "only showing top 1 row\n", 126 | "\n" 127 | ] 128 | } 129 | ], 130 | "source": [ 131 | "process_hollowing_minimal_privileges = spark.sql(\n", 132 | "'''\n", 133 | "SELECT * FROM df WHERE ((INT(granted_access) & 2312) == 2312) -- (0x0908) process access rights for PROCESS_VM_WRITE & PROCESS_VM_OPERATION & PROCESS_SUSPEND_RESUME & PROCESS_CREATE_PROCESS\n", 134 | "'''\n", 135 | ").show(1,False)" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": null, 141 | "metadata": {}, 142 | "outputs": [], 143 | "source": [] 144 | } 145 | ], 146 | "metadata": { 147 | "kernelspec": { 148 | "display_name": "PySpark_Python3", 149 | "language": "python", 150 | "name": "pyspark3" 151 | }, 152 | "language_info": { 153 | "codemirror_mode": { 154 | "name": "ipython", 155 | "version": 3 156 | }, 157 | "file_extension": ".py", 158 | "mimetype": "text/x-python", 159 | "name": "python", 160 | "nbconvert_exporter": "python", 161 | "pygments_lexer": "ipython3", 162 | "version": "3.7.3" 163 | } 164 | }, 165 | "nbformat": 4, 166 | "nbformat_minor": 4 167 | } 168 | -------------------------------------------------------------------------------- /Detection_Notebooks/Process_Hollow/Process_Hollowing_Transformed.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 9, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from pyspark.sql import SparkSession" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 10, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "spark = SparkSession.builder \\\n", 19 | " .appName(\"HELK JOIN\") \\\n", 20 | " .master(\"spark://helk-spark-master:7077\") \\\n", 21 | " .enableHiveSupport() \\\n", 22 | " .getOrCreate()" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 11, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "es_reader = (spark.read\n", 32 | " .format(\"org.elasticsearch.spark.sql\")\n", 33 | " .option(\"inferSchema\", \"true\")\n", 34 | " .option(\"es.read.field.as.array.include\", \"tags\")\n", 35 | " .option(\"es.nodes\",\"helk-elasticsearch:9200\")\n", 36 | " .option(\"es.net.http.auth.user\",\"elastic\")\n", 37 | ")" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 12, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "security_df = es_reader.load(\"logs-endpoint-winevent-security-*/\")" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 13, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "security_df.createOrReplaceTempView(\"security_events\")" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 14, 61 | "metadata": {}, 62 | "outputs": [], 63 | "source": [ 64 | "sysmon_df = es_reader.load(\"logs-endpoint-winevent-sysmon-*/\")" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 15, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "sysmon_df.createOrReplaceTempView(\"sysmon_events\")" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 16, 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "name": "stdout", 83 | "output_type": "stream", 84 | "text": [ 85 | "+------------------+---------+--------------------+-------------------+--------------------+----------------------+\n", 86 | "|host_name |user_name|process_parent_name |process_target_name|Sysmon_EID_1_LogonId|process_granted_access|\n", 87 | "+------------------+---------+--------------------+-------------------+--------------------+----------------------+\n", 88 | "|win10.marvel.local|thor |processhollowing.exe|svchost.exe |920687 |2097151 |\n", 89 | "|win10.marvel.local|thor |processhollowing.exe|cmd.exe |920687 |2097151 |\n", 90 | "|win10.marvel.local|thor |processhollowing.exe|cmd.exe |920687 |2097151 |\n", 91 | "|win10.marvel.local|thor |processhollowing.exe|svchost.exe |920687 |2097151 |\n", 92 | "|win10.marvel.local|thor |processhollowing.exe|svchost.exe |920687 |2097151 |\n", 93 | "|win10.marvel.local|thor |processhollowing.exe|cmd.exe |920687 |2097151 |\n", 94 | "|win10.marvel.local|thor |processhollowing.exe|svchost.exe |857049 |2097151 |\n", 95 | "|win10.marvel.local|thor |processhollowing.exe|cmd.exe |857049 |2097151 |\n", 96 | "|win10.marvel.local|thor |processhollowing.exe|cmd.exe |920687 |2097151 |\n", 97 | "|win10.marvel.local|thor |processhollowing.exe|svchost.exe |920687 |2097151 |\n", 98 | "+------------------+---------+--------------------+-------------------+--------------------+----------------------+\n", 99 | "only showing top 10 rows\n", 100 | "\n" 101 | ] 102 | } 103 | ], 104 | "source": [ 105 | "process_hollowing = spark.sql(\n", 106 | "'''\n", 107 | "SELECT \n", 108 | " c.host_name, \n", 109 | " c.user_name,\n", 110 | " c.process_parent_name,\n", 111 | " d.process_target_name,\n", 112 | " c.user_logon_id AS Sysmon_EID_1_LogonId,\n", 113 | " d.process_granted_access\n", 114 | "FROM security_events b\n", 115 | "JOIN sysmon_events c\n", 116 | " ON c.process_name = b.process_name\n", 117 | " AND c.event_id = 1\n", 118 | " AND c.user_name = b.user_name\n", 119 | "JOIN sysmon_events d\n", 120 | " ON c.process_guid = d.process_target_guid\n", 121 | " AND d.event_id = 10\n", 122 | " AND (d.process_granted_access & 2312) == 2312 -- 2312 = (0x0908) process access rights for PROCESS_VM_WRITE & PROCESS_VM_OPERATION & PROCESS_SUSPEND_RESUME & PROCESS_CREATE_PROCESS\n", 123 | " AND c.process_parent_guid = d.process_guid\n", 124 | " AND c.process_name = d.process_target_name\n", 125 | "JOIN sysmon_events e\n", 126 | " ON e.process_guid = c.process_parent_guid\n", 127 | " AND e.event_id = 5\n", 128 | " AND e.process_name = d.process_name\n", 129 | " AND c.process_parent_name = e.process_name \n", 130 | "JOIN sysmon_events f\n", 131 | " ON f.process_guid = c.process_parent_guid\n", 132 | " AND f.event_id = 7\n", 133 | " AND f.process_path = c.process_parent_path\n", 134 | " AND f.process_path = f.module_loaded\n", 135 | " AND f.signed = \"false\" -- Trivial for adversary to bypass. Here for extra context. Could take this out and whitelist processes.\n", 136 | "WHERE \n", 137 | " b.event_id = 4688\n", 138 | "'''\n", 139 | ").show(10,False)" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [] 148 | } 149 | ], 150 | "metadata": { 151 | "kernelspec": { 152 | "display_name": "PySpark_Python3", 153 | "language": "python", 154 | "name": "pyspark3" 155 | }, 156 | "language_info": { 157 | "codemirror_mode": { 158 | "name": "ipython", 159 | "version": 3 160 | }, 161 | "file_extension": ".py", 162 | "mimetype": "text/x-python", 163 | "name": "python", 164 | "nbconvert_exporter": "python", 165 | "pygments_lexer": "ipython3", 166 | "version": "3.7.3" 167 | } 168 | }, 169 | "nbformat": 4, 170 | "nbformat_minor": 4 171 | } 172 | -------------------------------------------------------------------------------- /Detection_Notebooks/Process_Reimaging/Process_Reimaging_Raw.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from openhunt.logparser import winlogbeat\n", 10 | "from pyspark.sql import SparkSession" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 2, 16 | "metadata": {}, 17 | "outputs": [ 18 | { 19 | "name": "stdout", 20 | "output_type": "stream", 21 | "text": [ 22 | "\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "win = winlogbeat()\n", 28 | "spark = SparkSession.builder.appName(\"Dataset\").config(\"spark.sql.caseSensitive\", \"True\").getOrCreate()\n", 29 | "print(spark)" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 3, 35 | "metadata": {}, 36 | "outputs": [ 37 | { 38 | "name": "stdout", 39 | "output_type": "stream", 40 | "text": [ 41 | "[+] Processing a Spark DataFrame..\n", 42 | "[+] Reading Mordor file..\n", 43 | "[+] Processing Data from Winlogbeat version 7..\n", 44 | "[+] DataFrame Returned !\n" 45 | ] 46 | } 47 | ], 48 | "source": [ 49 | "dataset = win.extract_nested_fields(\"process_reimaging_2019-09-12174205.json\",spark)" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 4, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "dataset.createOrReplaceTempView(\"processreimaging\")" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 5, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "name": "stdout", 68 | "output_type": "stream", 69 | "text": [ 70 | "+---------------+----------------+-------+---------+------------------------------------------------------------------------------+\n", 71 | "|computer_name |OriginalFileName|LogonId|ProcessId|TargetFilename |\n", 72 | "+---------------+----------------+-------+---------+------------------------------------------------------------------------------+\n", 73 | "|it001.shire.com|svchost.exe |0xa5b33|8632 |C:\\Users\\pgustavo\\Desktop\\CSProcessReimagingPOC\\bin\\Debug\\executing\\phase1.exe|\n", 74 | "|it001.shire.com|svchost.exe |0xa5b33|8632 |C:\\Users\\pgustavo\\Desktop\\CSProcessReimagingPOC\\bin\\Debug\\executing\\phase1.exe|\n", 75 | "+---------------+----------------+-------+---------+------------------------------------------------------------------------------+\n", 76 | "\n" 77 | ] 78 | } 79 | ], 80 | "source": [ 81 | "processreimaging = spark.sql(\n", 82 | "'''\n", 83 | "SELECT \n", 84 | " a.computer_name,\n", 85 | " a.OriginalFileName,\n", 86 | " a.LogonId,\n", 87 | " b.ProcessId,\n", 88 | " c.TargetFilename\n", 89 | "FROM processreimaging a\n", 90 | "JOIN processreimaging b\n", 91 | " ON a.ProcessGuid = b.ProcessGuid\n", 92 | " AND b.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 93 | " AND b.event_id = 7\n", 94 | " AND a.OriginalFileName = b.OriginalFileName\n", 95 | " AND a.Image = b.ImageLoaded\n", 96 | "JOIN processreimaging c\n", 97 | " ON a.ParentProcessGuid = c.ProcessGuid\n", 98 | " AND c.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 99 | " AND c.event_id = 11\n", 100 | " AND a.Image = c.TargetFilename \n", 101 | "WHERE\n", 102 | " a.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 103 | " AND a.event_id = 1\n", 104 | " AND a.IntegrityLevel = \"High\"\n", 105 | " AND LOWER(a.OriginalFileName) != LOWER(substring_index(a.Image, '\\\\\\\\', -1))\n", 106 | "'''\n", 107 | ").show(100,False)" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [] 116 | } 117 | ], 118 | "metadata": { 119 | "kernelspec": { 120 | "display_name": "PySpark_Python3", 121 | "language": "python", 122 | "name": "pyspark3" 123 | }, 124 | "language_info": { 125 | "codemirror_mode": { 126 | "name": "ipython", 127 | "version": 3 128 | }, 129 | "file_extension": ".py", 130 | "mimetype": "text/x-python", 131 | "name": "python", 132 | "nbconvert_exporter": "python", 133 | "pygments_lexer": "ipython3", 134 | "version": "3.7.3" 135 | } 136 | }, 137 | "nbformat": 4, 138 | "nbformat_minor": 4 139 | } 140 | -------------------------------------------------------------------------------- /Detection_Notebooks/Process_Reimaging/process_reimaging.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from openhunt.logparser import winlogbeat\n", 10 | "from pyspark.sql import SparkSession" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 2, 16 | "metadata": {}, 17 | "outputs": [ 18 | { 19 | "name": "stdout", 20 | "output_type": "stream", 21 | "text": [ 22 | "\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "win = winlogbeat()\n", 28 | "spark = SparkSession.builder.appName(\"Dataset\").config(\"spark.sql.caseSensitive\", \"True\").getOrCreate()\n", 29 | "print(spark)" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 3, 35 | "metadata": {}, 36 | "outputs": [ 37 | { 38 | "name": "stdout", 39 | "output_type": "stream", 40 | "text": [ 41 | "[+] Processing a Spark DataFrame..\n", 42 | "[+] Reading Mordor file..\n", 43 | "[+] Processing Data from Winlogbeat version 7..\n", 44 | "[+] DataFrame Returned !\n" 45 | ] 46 | } 47 | ], 48 | "source": [ 49 | "dataset = win.extract_nested_fields(\"process_reimaging_2019-09-12174205.json\",spark)" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 4, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "dataset.createOrReplaceTempView(\"processreimaging\")" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 5, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "name": "stdout", 68 | "output_type": "stream", 69 | "text": [ 70 | "+---------------+----------------+-------+---------+------------------------------------------------------------------------------+\n", 71 | "|computer_name |OriginalFileName|LogonId|ProcessId|TargetFilename |\n", 72 | "+---------------+----------------+-------+---------+------------------------------------------------------------------------------+\n", 73 | "|it001.shire.com|svchost.exe |0xa5b33|8632 |C:\\Users\\pgustavo\\Desktop\\CSProcessReimagingPOC\\bin\\Debug\\executing\\phase1.exe|\n", 74 | "|it001.shire.com|svchost.exe |0xa5b33|8632 |C:\\Users\\pgustavo\\Desktop\\CSProcessReimagingPOC\\bin\\Debug\\executing\\phase1.exe|\n", 75 | "+---------------+----------------+-------+---------+------------------------------------------------------------------------------+\n", 76 | "\n" 77 | ] 78 | } 79 | ], 80 | "source": [ 81 | "processreimaging = spark.sql(\n", 82 | "'''\n", 83 | "SELECT \n", 84 | " a.computer_name,\n", 85 | " a.OriginalFileName,\n", 86 | " a.LogonId,\n", 87 | " b.ProcessId,\n", 88 | " c.TargetFilename\n", 89 | "FROM processreimaging a\n", 90 | "JOIN processreimaging b\n", 91 | " ON a.ProcessGuid = b.ProcessGuid\n", 92 | " AND b.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 93 | " AND b.event_id = 7\n", 94 | " AND a.OriginalFileName = b.OriginalFileName\n", 95 | " AND a.Image = b.ImageLoaded\n", 96 | "JOIN processreimaging c\n", 97 | " ON a.ParentProcessGuid = c.ProcessGuid\n", 98 | " AND c.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 99 | " AND c.event_id = 11\n", 100 | " AND a.Image = c.TargetFilename \n", 101 | "WHERE\n", 102 | " a.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 103 | " AND a.event_id = 1\n", 104 | " AND a.IntegrityLevel = \"High\"\n", 105 | " AND LOWER(a.OriginalFileName) != LOWER(substring_index(a.Image, '\\\\\\\\', -1))\n", 106 | "'''\n", 107 | ").show(100,False)" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [] 116 | } 117 | ], 118 | "metadata": { 119 | "kernelspec": { 120 | "display_name": "PySpark_Python3", 121 | "language": "python", 122 | "name": "pyspark3" 123 | }, 124 | "language_info": { 125 | "codemirror_mode": { 126 | "name": "ipython", 127 | "version": 3 128 | }, 129 | "file_extension": ".py", 130 | "mimetype": "text/x-python", 131 | "name": "python", 132 | "nbconvert_exporter": "python", 133 | "pygments_lexer": "ipython3", 134 | "version": "3.7.3" 135 | } 136 | }, 137 | "nbformat": 4, 138 | "nbformat_minor": 4 139 | } 140 | -------------------------------------------------------------------------------- /Detection_Notebooks/Process_Reimaging/process_reimaging.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsecurity101/Detecting-Process-Injection-Techniques/3b77a4f1b374cd950a42a4fd680a32277effa61a/Detection_Notebooks/Process_Reimaging/process_reimaging.tar.gz -------------------------------------------------------------------------------- /Detection_Notebooks/Reflective_DLL_Injection/Reflective_DLL_Injection.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsecurity101/Detecting-Process-Injection-Techniques/3b77a4f1b374cd950a42a4fd680a32277effa61a/Detection_Notebooks/Reflective_DLL_Injection/Reflective_DLL_Injection.tar.gz -------------------------------------------------------------------------------- /Detection_Notebooks/Reflective_DLL_Injection/Reflective_DLL_Injection_Raw.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from openhunt.logparser import winlogbeat\n", 10 | "from pyspark.sql import SparkSession\n", 11 | "from pyspark.sql.functions import *" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 2, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "win = winlogbeat()\n", 21 | "spark = SparkSession.builder.appName(\"Process\").config(\"spark.sql.caseSensitive\", \"True\").getOrCreate()" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 3, 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "name": "stdout", 31 | "output_type": "stream", 32 | "text": [ 33 | "[+] Processing a Spark DataFrame..\n", 34 | "[+] Reading Mordor file..\n", 35 | "[+] Processing Data from Winlogbeat version 6..\n", 36 | "[+] DataFrame Returned !\n" 37 | ] 38 | } 39 | ], 40 | "source": [ 41 | "process_injection = win.extract_nested_fields(\"empire_psinject_2019-05-18200432.json\",spark)" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 4, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "process_injection.createOrReplaceTempView(\"process_injection\")" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 5, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "ReflectiveDLL_ProcessInjection = spark.sql(\n", 60 | "\n", 61 | "'''\n", 62 | "SELECT \n", 63 | " b.computer_name,\n", 64 | " ltrim('0x', b.GrantedAccess) as granted_access,\n", 65 | " a.SourceImage,\n", 66 | " a.SourceProcessGuid,\n", 67 | " a.NewThreadId, \n", 68 | " a.TargetProcessId,\n", 69 | " a.TargetImage\n", 70 | "FROM process_injection a\n", 71 | "JOIN process_injection b \n", 72 | " ON a.SourceProcessGuid = b.SourceProcessGUID \n", 73 | " AND b.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 74 | " AND b.event_id = 10\n", 75 | " AND a.TargetProcessGuid = b.TargetProcessGUID\n", 76 | "WHERE a.channel = \"Microsoft-Windows-Sysmon/Operational\"\n", 77 | " AND a.event_id = 8\n", 78 | "'''\n", 79 | ")" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": 6, 85 | "metadata": {}, 86 | "outputs": [], 87 | "source": [ 88 | "df = ReflectiveDLL_ProcessInjection.select(\"computer_name\", conv(ReflectiveDLL_ProcessInjection.granted_access, 16, 10).alias(\"granted_access\"), \"SourceImage\", \"SourceProcessGuid\", \"NewThreadId\", \"TargetProcessId\", \"TargetImage\")" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 7, 94 | "metadata": {}, 95 | "outputs": [], 96 | "source": [ 97 | "df.createOrReplaceTempView(\"df\")" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 8, 103 | "metadata": {}, 104 | "outputs": [ 105 | { 106 | "name": "stdout", 107 | "output_type": "stream", 108 | "text": [ 109 | "+---------------+--------------+---------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 110 | "|computer_name |granted_access|SourceImage |SourceProcessGuid |NewThreadId|TargetProcessId|TargetImage |\n", 111 | "+---------------+--------------+---------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 112 | "|HR001.shire.com|2047999 |C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe|{03ba39f5-50b2-5ce0-0000-00109995c501}|9180 |7924 |C:\\Windows\\System32\\notepad.exe|\n", 113 | "+---------------+--------------+---------------------------------------------------------+--------------------------------------+-----------+---------------+-------------------------------+\n", 114 | "only showing top 1 row\n", 115 | "\n" 116 | ] 117 | } 118 | ], 119 | "source": [ 120 | "eid_8_10_minimal_privileges = spark.sql(\n", 121 | "'''\n", 122 | "SELECT * FROM df WHERE ((INT(granted_access) & 5178) == 5178) -- 5178 is decimal for 0x143A. The minimal privileges you need to access process handle\n", 123 | "'''\n", 124 | ").show(1,False)" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": null, 130 | "metadata": {}, 131 | "outputs": [], 132 | "source": [] 133 | } 134 | ], 135 | "metadata": { 136 | "kernelspec": { 137 | "display_name": "PySpark_Python3", 138 | "language": "python", 139 | "name": "pyspark3" 140 | }, 141 | "language_info": { 142 | "codemirror_mode": { 143 | "name": "ipython", 144 | "version": 3 145 | }, 146 | "file_extension": ".py", 147 | "mimetype": "text/x-python", 148 | "name": "python", 149 | "nbconvert_exporter": "python", 150 | "pygments_lexer": "ipython3", 151 | "version": "3.7.3" 152 | } 153 | }, 154 | "nbformat": 4, 155 | "nbformat_minor": 4 156 | } 157 | -------------------------------------------------------------------------------- /Detection_Notebooks/Reflective_DLL_Injection/Reflective_DLL_Injection_Transformed.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 14, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from pyspark.sql import SparkSession" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 15, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "spark = SparkSession.builder \\\n", 19 | " .appName(\"HELK Reader\") \\\n", 20 | " .master(\"spark://helk-spark-master:7077\") \\\n", 21 | " .enableHiveSupport() \\\n", 22 | " .getOrCreate()" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 16, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "es_reader = (spark.read\n", 32 | " .format(\"org.elasticsearch.spark.sql\")\n", 33 | " .option(\"inferSchema\", \"true\")\n", 34 | " .option(\"es.read.field.as.array.include\", \"tags\")\n", 35 | " .option(\"es.nodes\",\"helk-elasticsearch:9200\")\n", 36 | " .option(\"es.net.http.auth.user\",\"elastic\")\n", 37 | ")" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 17, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "sysmon_df = es_reader.load(\"logs-endpoint-winevent-sysmon-*/\")" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 18, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "sysmon_df.createOrReplaceTempView(\"sysmon_events\")" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 28, 61 | "metadata": {}, 62 | "outputs": [ 63 | { 64 | "name": "stdout", 65 | "output_type": "stream", 66 | "text": [ 67 | "+---------------------------------------------------------+-------------------+-----------------+-------------+----------+----------------------+\n", 68 | "|process_path |process_target_name|process_target_id|thread_new_id|process_id|process_granted_access|\n", 69 | "+---------------------------------------------------------+-------------------+-----------------+-------------+----------+----------------------+\n", 70 | "|c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe|notepad.exe |3124 |7940 |5452 |2047999 |\n", 71 | "|c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe|notepad.exe |3124 |7940 |5452 |2047999 |\n", 72 | "|c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe|notepad.exe |7924 |7388 |5452 |2047999 |\n", 73 | "|c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe|notepad.exe |7924 |7388 |5452 |2047999 |\n", 74 | "|c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe|notepad.exe |7924 |5376 |5452 |2047999 |\n", 75 | "|c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe|notepad.exe |7924 |5376 |5452 |2047999 |\n", 76 | "|c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe|notepad.exe |7924 |7640 |5452 |2047999 |\n", 77 | "|c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe|notepad.exe |7924 |7640 |5452 |2047999 |\n", 78 | "|c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe|notepad.exe |7924 |7332 |5452 |2047999 |\n", 79 | "|c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe|notepad.exe |7924 |7332 |5452 |2047999 |\n", 80 | "+---------------------------------------------------------+-------------------+-----------------+-------------+----------+----------------------+\n", 81 | "only showing top 10 rows\n", 82 | "\n" 83 | ] 84 | } 85 | ], 86 | "source": [ 87 | "ReflectiveDLL_ProcessInjection = spark.sql(\n", 88 | "'''\n", 89 | "SELECT \n", 90 | " b.process_path,\n", 91 | " b.process_target_name,\n", 92 | " b.process_target_id,\n", 93 | " b.thread_new_id,\n", 94 | " a.process_id,\n", 95 | " a.process_granted_access\n", 96 | "FROM sysmon_events b\n", 97 | "JOIN sysmon_events a\n", 98 | "ON a.process_guid = b.process_guid\n", 99 | "AND a.event_id = 10\n", 100 | "AND (a.process_granted_access & 5178) == 5178\n", 101 | "\n", 102 | "WHERE b.event_id = 8\n", 103 | "AND NOT b.process_name = \"csrss.exe\"\n", 104 | "'''\n", 105 | ").show(10,False)\n" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": null, 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [] 114 | } 115 | ], 116 | "metadata": { 117 | "kernelspec": { 118 | "display_name": "PySpark_Python3", 119 | "language": "python", 120 | "name": "pyspark3" 121 | }, 122 | "language_info": { 123 | "codemirror_mode": { 124 | "name": "ipython", 125 | "version": 3 126 | }, 127 | "file_extension": ".py", 128 | "mimetype": "text/x-python", 129 | "name": "python", 130 | "nbconvert_exporter": "python", 131 | "pygments_lexer": "ipython3", 132 | "version": "3.7.3" 133 | } 134 | }, 135 | "nbformat": 4, 136 | "nbformat_minor": 4 137 | } 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Detecting Process Injection Techniques: 2 | This is a repository that is meant to hold detections for various process injection techniques. 3 | 4 | # General Information: 5 | 6 | * Data analytics written within Jupyter Notebooks can be found within the `Detection_Notebooks` folder. 7 | 8 | * Datasets of each technique can be found within the respective folders. 9 | 10 | ## Technqiues Covered Within This Project: 11 | * DLL Injection (CreateRemoteThread & RtlCreateUserThread) 12 | * Reflective DLL Injection 13 | * Process Hollowing 14 | * Process Reimaging (not necessarily injection, but still useful) 15 | * Hook Injection via SetWindowsHookEx 16 | 17 | ## Resources: 18 | POC's: 19 | * https://github.com/theevilbit/injection 20 | * https://github.com/secrary/InjectProc 21 | * https://github.com/djhohnstein/ProcessReimaging 22 | * [psinject empire dataset](https://github.com/hunters-forge/mordor/blob/master/datasets/small/windows/defense_evasion/empire_psinject.tar.gz) 23 | ## Reading From The Datasets: 24 | 25 | - You can read from the json file directly from within the notebooks (see Raw notebooks for an example). 26 | 27 | - You can ingest the datasets into your ELK stack by utilziing `kafkacat`. Follow these steps: 28 | 29 | * Untar the dataset of choice: 30 | 31 | 32 | tar -xzvf dataset.tar.gz 33 | 34 | 35 | - Use kafkacat to send dataset to Kafka broker: 36 | 37 | 38 | kafkacat -b :9092 -t winlogbeat -P -l dataset.json 39 | 40 | 41 | 42 | ## Injection Information: 43 | * https://www.endgame.com/blog/technical-blog/ten-process-injection-techniques-technical-survey-common-and-trending-process 44 | * https://warroom.rsmus.com/dll-injection-part-1-setwindowshookex/ 45 | 46 | # Authors: 47 | * [Josh Prager](https://twitter.com/Praga_Prag) 48 | 49 | * [Jonathan Johnson](https://twitter.com/jsecurity101) 50 | 51 | * [David Polojac](https://twitter.com/@poloh4ck) 52 | --------------------------------------------------------------------------------