diff --git a/SSP_DLL.sln b/SSP_DLL.sln
new file mode 100644
index 0000000..52d3eee
--- /dev/null
+++ b/SSP_DLL.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36121.58 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SSP_DLL", "SSP_DLL\SSP_DLL.vcxproj", "{409AFE33-D438-4590-8F91-2C0C83113FE5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {409AFE33-D438-4590-8F91-2C0C83113FE5}.Debug|x64.ActiveCfg = Debug|x64
+ {409AFE33-D438-4590-8F91-2C0C83113FE5}.Debug|x64.Build.0 = Debug|x64
+ {409AFE33-D438-4590-8F91-2C0C83113FE5}.Debug|x86.ActiveCfg = Debug|Win32
+ {409AFE33-D438-4590-8F91-2C0C83113FE5}.Debug|x86.Build.0 = Debug|Win32
+ {409AFE33-D438-4590-8F91-2C0C83113FE5}.Release|x64.ActiveCfg = Release|x64
+ {409AFE33-D438-4590-8F91-2C0C83113FE5}.Release|x64.Build.0 = Release|x64
+ {409AFE33-D438-4590-8F91-2C0C83113FE5}.Release|x86.ActiveCfg = Release|Win32
+ {409AFE33-D438-4590-8F91-2C0C83113FE5}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {971508A5-D2BE-4254-BCAA-3B0E44B7E633}
+ EndGlobalSection
+EndGlobal
diff --git a/SSP_DLL/SSP_DLL.vcxproj b/SSP_DLL/SSP_DLL.vcxproj
new file mode 100644
index 0000000..082a45a
--- /dev/null
+++ b/SSP_DLL/SSP_DLL.vcxproj
@@ -0,0 +1,170 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 17.0
+ Win32Proj
+ {409afe33-d438-4590-8f91-2c0c83113fe5}
+ SSPDLL
+ 10.0
+ RublonSSP
+
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;SSPDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;SSPDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ _DEBUG;SSPDLL_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ NotUsing
+
+
+ stdcpp20
+
+
+ Console
+ true
+ false
+ iphlpapi.lib;ws2_32.lib;winhttp.lib;Secur32.lib;%(AdditionalDependencies)
+ rublonssp.def
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;SSPDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ NotUsing
+
+
+ MultiThreaded
+ false
+ stdcpp20
+
+
+ Windows
+ true
+ false
+ rublonssp.def
+ iphlpapi.lib;ws2_32.lib;winhttp.lib;Secur32.lib;WtsApi32.lib;Netapi32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SSP_DLL/SSP_DLL.vcxproj.filters b/SSP_DLL/SSP_DLL.vcxproj.filters
new file mode 100644
index 0000000..06ee9f5
--- /dev/null
+++ b/SSP_DLL/SSP_DLL.vcxproj.filters
@@ -0,0 +1,62 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/SSP_DLL/connectorSSP.cpp b/SSP_DLL/connectorSSP.cpp
new file mode 100644
index 0000000..1dd95cf
--- /dev/null
+++ b/SSP_DLL/connectorSSP.cpp
@@ -0,0 +1,178 @@
+#include "connectorSSP.h"
+
+NTSTATUS manage_mfa_session(const char *json_data) {
+ NTSTATUS mfa_status = STATUS_UNSUCCESSFUL;
+ HINTERNET http_session = NULL;
+ HINTERNET http_connect = NULL;
+ HINTERNET http_request = NULL;
+
+ DWORD http_status = 0;
+
+ if (open_http_connection(&http_session, &http_connect, &http_request,
+ mfa_server_ip, mfa_server_destination_port, web_api_endpoint)) {
+ if (handle_http_traffic(&http_request, json_data, &http_status)) {
+ BYTE* http_response = NULL;
+ DWORD http_response_size = 0;
+ if (process_received_data(&http_request, &http_response, &http_response_size)) {
+ int wide_http_response_size = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)http_response, http_response_size, NULL, 0);
+ if (wide_http_response_size > 0) {
+ LPWSTR wide_http_response = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, wide_http_response_size * sizeof(wchar_t));
+ if (wide_http_response) {
+ MultiByteToWideChar(CP_UTF8, 0, (LPCCH)http_response, http_response_size, wide_http_response, wide_http_response_size);
+ log_line(LOG_TYPE_INFO, L" -> Odpowiedz z serwera MFA: %s", wide_http_response);
+ HeapFree(GetProcessHeap(), 0, wide_http_response);
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, http_response);
+ }
+ else {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w odczytywaniu odpowiedzi HTTP", L"process_received_data");
+ }
+ }
+ else {
+ WinHttpCloseHandle(http_request);
+ WinHttpCloseHandle(http_connect);
+ WinHttpCloseHandle(http_session);
+ }
+ if (http_status == 200)
+ mfa_status = STATUS_SUCCESS;
+ }
+
+ if(http_request) WinHttpCloseHandle(http_request);
+ if(http_connect) WinHttpCloseHandle(http_connect);
+ if(http_session) WinHttpCloseHandle(http_session);
+
+ return mfa_status;
+}
+
+BOOL open_http_connection(HINTERNET *session_handle, HINTERNET *connection_handle, HINTERNET *request_handle,
+ LPCWSTR ip, INTERNET_PORT port, LPCWSTR web_api_path) {
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ *session_handle = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
+
+ if (!*session_handle) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w WinHttpOpen: %lu", function_name, GetLastError());
+ return FALSE;
+ }
+
+ *connection_handle = WinHttpConnect(*session_handle, ip, port, 0);
+ if (!*connection_handle) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w WinHttpConnect: %lu", function_name, GetLastError());
+ WinHttpCloseHandle(*session_handle);
+ return FALSE;
+ }
+
+ *request_handle = WinHttpOpenRequest(*connection_handle, L"POST", web_api_path, NULL,
+ WINHTTP_NO_REFERER,WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
+
+ if (!*request_handle) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w WinHttpOpenRequest: %lu", function_name, GetLastError());
+ WinHttpCloseHandle(*connection_handle);
+ WinHttpCloseHandle(*session_handle);
+ return FALSE;
+ }
+
+ if (!WinHttpAddRequestHeaders(*request_handle, L"Content-Type: application/json; charset=utf-8\r\n",
+ -1, WINHTTP_ADDREQ_FLAG_ADD)) {
+ log_line(LOG_TYPE_WARNING, L"[%s] Blad w WinHttpAddRequestHeaders: %lu", function_name, GetLastError());
+ }
+ return TRUE;
+}
+
+BOOL handle_http_traffic(HINTERNET *request_handle, const char *json_data, DWORD *status) {
+ DWORD json_length = (DWORD)strlen(json_data);
+
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ if (!WinHttpSendRequest(*request_handle, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
+ (LPVOID)json_data, json_length, json_length, 0)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w WinHttpSendRequest: %lu", function_name, GetLastError());
+ return false;
+ }
+
+ if (!WinHttpReceiveResponse(*request_handle, NULL)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w WinHttpReceiveResponse: %lu", function_name, GetLastError());
+ return false;
+ }
+
+ DWORD statusCode = 0;
+ DWORD size = sizeof(statusCode);
+ if (WinHttpQueryHeaders(*request_handle,
+ WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ &statusCode, &size, WINHTTP_NO_HEADER_INDEX)) {
+ *status = statusCode;
+ log_line(LOG_TYPE_DEBUG, L"[%s] status HTTP: %lu", function_name, statusCode);
+ }
+ else {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w WinHttpQueryHeaders: %lu", function_name, GetLastError());
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL process_received_data(HINTERNET *request_handle, BYTE** response_data, DWORD* response_size) {
+ BYTE* buffer = NULL;
+ DWORD totalSize = 0;
+
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ while (true) {
+ DWORD available = 0;
+ if (!WinHttpQueryDataAvailable(*request_handle, &available)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w WinHttpQueryDataAvailable: %lu", function_name, GetLastError());
+ break;
+ }
+ log_line(LOG_TYPE_DEBUG, L"[%s] Dostepne bajty: %lu", function_name, available);
+ if (available == 0) {
+ break;
+ }
+
+ BYTE* temp = NULL;
+ if (buffer == NULL) {
+ temp = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, totalSize + available);
+ }
+ else {
+ temp = (BYTE*)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer, totalSize + available);
+ }
+ if (!temp) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w HeapRealloc\\Alloc", function_name);
+ if (buffer) HeapFree(GetProcessHeap(), 0, buffer);
+ buffer = NULL;
+ break;
+ }
+
+ buffer = temp;
+ //printf("Buffer resized: total size now %lu\n", totalSize + available);
+ //log_line(LOG_TYPE_DEBUG, L"[%s] Zmiana rozmiaru bufora, calkowity rozmiar po zmianie: %lu", function_name, totalSize + available);
+
+ DWORD bytesRead = 0;
+ if (WinHttpReadData(*request_handle, buffer + totalSize, available, &bytesRead)) {
+ //log_line(LOG_TYPE_DEBUG, L"[%s] Odczytano bajtow: %lu", function_name, bytesRead);
+ totalSize += bytesRead;
+ }
+ else {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w WinHttpReadData: %lu", function_name, GetLastError());
+ if (buffer) HeapFree(GetProcessHeap(), 0, buffer);
+ buffer = NULL;
+ break;
+ }
+ }
+ bool success = (buffer != NULL && totalSize > 0);
+ const wchar_t* success_string = success ? L"SUCCESS" : L"FAIL";
+ log_line(LOG_TYPE_DEBUG, L"[%s] Status odczytywania: %s, odczytano lacznie: %lu bajtow", function_name, success_string, totalSize);
+ if (success) {
+ *response_data = buffer;
+ *response_size = totalSize;
+ }
+ else {
+ if (buffer)
+ HeapFree(GetProcessHeap(), 0, buffer);
+ }
+
+ return success;
+}
\ No newline at end of file
diff --git a/SSP_DLL/connectorSSP.h b/SSP_DLL/connectorSSP.h
new file mode 100644
index 0000000..73ad181
--- /dev/null
+++ b/SSP_DLL/connectorSSP.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "utilsSSP.h"
+
+#include
+
+constexpr LPCWSTR mfa_server_ip = L"192.168.56.104";
+constexpr INTERNET_PORT mfa_server_destination_port = 8080;
+constexpr LPCWSTR web_api_endpoint = L"/connect";
+
+NTSTATUS manage_mfa_session(const char* json_data);
+
+BOOL open_http_connection(HINTERNET* session_handle, HINTERNET* connection_handle, HINTERNET* request_handle,
+ LPCWSTR ip, INTERNET_PORT port, LPCWSTR web_api_path);
+
+BOOL handle_http_traffic(HINTERNET* request_handle, const char* json_data, DWORD* status);
+
+BOOL process_received_data(HINTERNET* request_handle, BYTE** responseData, DWORD* responseSize);
\ No newline at end of file
diff --git a/SSP_DLL/domainUtilsSSP.cpp b/SSP_DLL/domainUtilsSSP.cpp
new file mode 100644
index 0000000..bf4891f
--- /dev/null
+++ b/SSP_DLL/domainUtilsSSP.cpp
@@ -0,0 +1,199 @@
+#include "domainUtilsSSP.h"
+
+#include "utilsSSP.h"
+
+DOMAIN_INFO domain_info = { 0 };
+
+USER_INFO* domain_users = NULL;
+
+LONG domain_monitor_thread_counter = 0;
+
+
+HRESULT get_domain_info() {
+ DSROLE_PRIMARY_DOMAIN_INFO_BASIC* domain_role_info = NULL;
+
+ DWORD status = DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (PBYTE*)&domain_role_info);
+ if (status == ERROR_SUCCESS) {
+ domain_info.is_domain_controller = (domain_role_info->MachineRole == DsRole_RolePrimaryDomainController ||
+ domain_role_info->MachineRole == DsRole_RoleBackupDomainController);
+ domain_info.is_machine_domain_joined = (domain_role_info->MachineRole != DsRole_RoleStandaloneWorkstation &&
+ domain_role_info->MachineRole != DsRole_RoleStandaloneServer);
+ StringCchCopyW(domain_info.NetBIOS_name, ARRAYSIZE(domain_info.NetBIOS_name), domain_role_info->DomainNameFlat);
+ StringCchCopyW(domain_info.DNS_domain_name, ARRAYSIZE(domain_info.DNS_domain_name), domain_role_info->DomainNameDns);
+ DsRoleFreeMemory(domain_role_info);
+ }
+ else {
+ return HRESULT_FROM_WIN32(status);
+ }
+
+ SID_NAME_USE pe_use;
+ BYTE sid_buffer[SECURITY_MAX_SID_SIZE] = { 0 };
+ DWORD sid_size = sizeof(sid_buffer);
+ WCHAR referenced_domain[MAX_PATH];
+ DWORD domain_size = ARRAYSIZE(referenced_domain);
+
+ if (!LookupAccountNameW(NULL, domain_info.DNS_domain_name, sid_buffer, &sid_size,
+ referenced_domain, &domain_size, &pe_use
+ )) {
+ DWORD err = GetLastError();
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad LookupAccountNameW, kod bledu: %lu", L"get_domain_info", GetLastError());
+ return HRESULT_FROM_WIN32(err);
+ }
+
+ DWORD len = GetLengthSid(sid_buffer);
+ domain_info.domain_SID = (PSID)LocalAlloc(LMEM_FIXED, len);
+ if (!domain_info.domain_SID) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad alokacji pamieci dla SID", L"get_domain_info");
+ return E_OUTOFMEMORY;
+ }
+ if (!CopySid(len, domain_info.domain_SID, sid_buffer)) {
+ DWORD err = GetLastError();
+ LocalFree(domain_info.domain_SID);
+ domain_info.domain_SID = NULL;
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w kopiowaniu SID", L"get_domain_info");
+ return HRESULT_FROM_WIN32(err);
+ }
+ return S_OK;
+}
+
+HRESULT get_domain_users() {
+ DWORD total_users = 0;
+ DWORD read = 0;
+
+ WCHAR function_name[] = L"get_domain_users";
+
+ NET_API_STATUS status = NetUserEnum(
+ NULL, 0, FILTER_NORMAL_ACCOUNT,
+ NULL, 0, &read, &total_users, NULL
+ );
+ if (status != ERROR_SUCCESS && status != ERROR_MORE_DATA) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad NetUserEnum, kod bledu: %lu", function_name, status);
+ return HRESULT_FROM_WIN32(status);
+ }
+ if (total_users == 0) {
+ log_line(LOG_TYPE_WARNING, L"[%s] Nie odnaleziono uzytkownikow domeny...", function_name);
+ return S_OK;
+ }
+
+ HANDLE hHeap = GetProcessHeap();
+ domain_users = (USER_INFO*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(USER_INFO) * total_users);
+ if (!domain_users)
+ {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad alokacji pamieci dla USER_INFO", function_name);
+ return E_OUTOFMEMORY;
+ }
+
+ USER_INFO_0* user_info_buff = NULL;
+ DWORD resume = 0, read_sec = 0, total_users_sec = 0;
+ DWORD user_index = 0;
+ int regular_users = 0;
+ int system_users = 0;
+
+ DWORD start = GetTickCount();
+
+ do
+ {
+ status = NetUserEnum(NULL, 0, FILTER_NORMAL_ACCOUNT, (LPBYTE*)&user_info_buff,
+ MAX_PREFERRED_LENGTH, &read_sec, &total_users_sec, &resume
+ );
+
+ if ((status == NERR_Success || status == ERROR_MORE_DATA) && user_info_buff)
+ {
+ for (DWORD i = 0; i < read_sec && user_index < total_users; ++i)
+ {
+ LPCWSTR name = user_info_buff[i].usri0_name;
+
+ BYTE sidBuffer[512];
+ DWORD sidSize = sizeof(sidBuffer);
+ WCHAR domain[256];
+ DWORD domainSize = ARRAYSIZE(domain);
+ SID_NAME_USE sidType;
+
+ if (LookupAccountNameW(NULL, name, sidBuffer, &sidSize, domain, &domainSize, &sidType))
+ {
+ DWORD rid = *GetSidSubAuthority((PSID)sidBuffer, *GetSidSubAuthorityCount((PSID)sidBuffer) - 1);
+ domain_users[user_index].user_rid = rid;
+ (rid < 1000) ? ++system_users : ++regular_users;
+
+ StringCchCopyW(domain_users[user_index].user_name, ARRAYSIZE(domain_users[user_index].user_name), name);
+ ++user_index;
+ }
+ }
+
+ NetApiBufferFree(user_info_buff);
+ user_info_buff = NULL;
+ }
+
+ } while (status == ERROR_MORE_DATA && user_index < total_users_sec);
+
+ DWORD totalTime = GetTickCount() - start;
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Pobrano informacje o uzytkownikach domenowych: Uzytkownikow regularnych: %d, uzytkownikow systemowych: %d, czas wykonania: %.2f s.",
+ function_name,
+ regular_users,
+ system_users,
+ totalTime / 1000.0);
+
+ return S_OK;
+}
+
+DWORD WINAPI run_dc_monitor(LPVOID) {
+ const DWORD maxRetries = 30;
+ const DWORD retryDelayMs = 1000;
+
+ WCHAR function_name[] = L"DomainMonitor";
+
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Start monitora gotowosci domeny...",
+ function_name
+ );
+
+ DWORD start = GetTickCount();
+
+ for (DWORD i = 0; i < maxRetries; ++i) {
+ HRESULT res = get_domain_info();
+ if (SUCCEEDED(res)) {
+ LPWSTR sid_string = NULL;
+ if (!ConvertSidToStringSidW(domain_info.domain_SID, &sid_string)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w konwersji SID", function_name);
+ }
+ LocalFree(sid_string);
+
+ DWORD elapsed_ms = GetTickCount() - start;
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Informacje o domenie gotowe po %.2f s",
+ function_name,
+ elapsed_ms / 1000.0);
+
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Status maszyny -- Nazwa DNS domeny: %s, Nazwa NetBIOS: %s, PSID domeny: %s, Czy w domenie: %s, Czy kontroler domeny: %s",
+ function_name,
+ domain_info.DNS_domain_name,
+ domain_info.NetBIOS_name,
+ sid_string,
+ (domain_info.is_machine_domain_joined) ? L"TAK" : L"NIE",
+ (domain_info.is_domain_controller) ? L"TAK" : L"NIE"
+ );
+
+ domain_info.initialized = TRUE;
+
+ return 0;
+ }
+
+ if (res != HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) {
+ log_line(LOG_TYPE_ERROR,
+ L"[%s] Nie mozna pobrac danych do ustalenia statusu DC: 0x%08X",
+ function_name,
+ res);
+ return 1;
+ }
+ Sleep(retryDelayMs);
+ }
+
+ DWORD totalTime = GetTickCount() - start;
+ log_line(LOG_TYPE_WARNING,
+ L"[%s] Timeout — nie pobrano danych o domenie po %lu ms.",
+ function_name,
+ totalTime);
+ return 2;
+}
\ No newline at end of file
diff --git a/SSP_DLL/domainUtilsSSP.h b/SSP_DLL/domainUtilsSSP.h
new file mode 100644
index 0000000..e1d2bdb
--- /dev/null
+++ b/SSP_DLL/domainUtilsSSP.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "main.h"
+
+#include
+#include
+#include
+
+typedef struct _DOMAIN_INFO {
+ BOOL initialized;
+ BOOL is_machine_domain_joined;
+ BOOL is_domain_controller;
+ PSID domain_SID;
+ WCHAR DNS_domain_name[256];
+ WCHAR NetBIOS_name[64];
+} DOMAIN_INFO;
+
+typedef struct _USER_INFO {
+ DWORD user_rid;
+ WCHAR user_name[256];
+} USER_INFO;
+
+extern DOMAIN_INFO domain_info;
+extern USER_INFO* domain_users;
+extern LONG domain_monitor_thread_counter;
+
+DWORD WINAPI run_dc_monitor(LPVOID);
+
+HRESULT get_domain_info();
+HRESULT get_domain_users();
\ No newline at end of file
diff --git a/SSP_DLL/interprocessSSP.cpp b/SSP_DLL/interprocessSSP.cpp
new file mode 100644
index 0000000..3df446d
--- /dev/null
+++ b/SSP_DLL/interprocessSSP.cpp
@@ -0,0 +1,952 @@
+#include "interprocessSSP.h"
+#include "connectorSSP.h"
+
+EXISTING_RDP_SESSION remote_interactive_sessions[MAX_RDP_SESSIONS] = { 0 };
+
+RDP_SESSION_ARRAY rdp_sessions = { 0 };
+
+
+PSID convert_sidstring_to_sid(LPCWSTR sid_str) {
+ PSID p_sid = NULL;
+ if (!ConvertStringSidToSidW(sid_str, &p_sid)) {
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+ log_line(LOG_TYPE_WARNING,
+ L"[%s] Blad ConvertStringSidToSidW: %lu", function_name, GetLastError()
+ );
+ return NULL;
+ }
+ return p_sid;
+}
+
+void get_LUID_string(const PLUID luid, PWSTR out, size_t out_len) {
+ if (!luid) {
+ StringCchCopyW(out, out_len, L"");
+ return;
+ }
+ StringCchPrintfW(out, out_len, L"%08x-%08x", luid->HighPart, luid->LowPart);
+}
+
+BOOL get_PIDs_from_sessionID(DWORD in_session_id, RELATED_PROCESSES *session_processes, BOOL update_flag) {
+ WCHAR function_name[40] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (hSnap == INVALID_HANDLE_VALUE) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad CreateToolhelp32Snapshot", function_name);
+ return FALSE;
+ }
+
+ PROCESSENTRY32W pe;
+ pe.dwSize = sizeof(pe);
+
+ if (Process32FirstW(hSnap, &pe)) {
+ do {
+ /*
+ * w przypadku gdy procesow jest wiecej niz 5
+ * zrob realloc - powieksz 2 razy, powinno wystarczyc
+ */
+ if (session_processes->count >= INITIAL_PROCESSES_COUNT) {
+ RELATED_PROCESS* new_processes = (RELATED_PROCESS*)HeapReAlloc(
+ GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ session_processes->process,
+ INITIAL_PROCESSES_COUNT * 2 * sizeof(RELATED_PROCESS));
+
+ if (!new_processes) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w HeapReAlloc", function_name);
+ return FALSE;
+ }
+ session_processes->process = new_processes;
+ }
+ DWORD procSessionId = 0;
+ if (ProcessIdToSessionId(pe.th32ProcessID, &procSessionId)) {
+ if (procSessionId == in_session_id) {
+ // jesli PID jest jednym z istotnych procesow systemowych - NIE UBIJAJ
+ if (CompareStringOrdinal(pe.szExeFile, -1, L"services.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"smss.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"wininit.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"lsass.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"csrss.exe", -1, TRUE) == CSTR_EQUAL)
+ {
+ continue;
+ }
+ if (update_flag) {
+ for (DWORD i = 0; i < session_processes->count; i++) {
+ if (CompareStringOrdinal(pe.szExeFile, -1,
+ session_processes->process[session_processes->count].process_name,
+ -1, TRUE) == CSTR_EQUAL &&
+ session_processes->process[session_processes->count].pid == pe.th32ProcessID)
+ {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Dla sesji ID = %lu, proces = %s, PID = %lu. juz istnieje...",
+ function_name,
+ session_processes->process[session_processes->count].process_name,
+ session_processes->process[session_processes->count].pid
+ );
+ continue;
+ }
+ session_processes->process[session_processes->count].pid = pe.th32ProcessID;
+ session_processes->process[session_processes->count].pid;
+ StringCchCopyW(session_processes->process[session_processes->count].process_name,
+ ARRAYSIZE(session_processes->process[session_processes->count].process_name),
+ pe.szExeFile);
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Wykryto dodatkowy proces dla sesji = %s, PID = %lu.",
+ function_name,
+ session_processes->process[session_processes->count].process_name,
+ session_processes->process[session_processes->count].pid
+ );
+ session_processes->count++;
+ }
+
+ }
+ else {
+ session_processes->process[session_processes->count].pid = pe.th32ProcessID;
+ session_processes->process[session_processes->count].pid;
+ StringCchCopyW(session_processes->process[session_processes->count].process_name,
+ ARRAYSIZE(session_processes->process[session_processes->count].process_name),
+ pe.szExeFile);
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Wykryto proces dla sesji = %s, PID = %lu.",
+ function_name,
+ session_processes->process[session_processes->count].process_name,
+ session_processes->process[session_processes->count].pid
+ );
+ session_processes->count++;
+ }
+ }
+ }
+ } while (Process32NextW(hSnap, &pe));
+ }
+
+ return TRUE;
+}
+
+BOOL get_PID_from_SessionID(DWORD in_session_id, DWORD *pid, WCHAR *pid_exe_name) {
+ WCHAR function_name[40] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ DWORD processes_count = 0;
+
+ HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (hSnap == INVALID_HANDLE_VALUE) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad CreateToolhelp32Snapshot", function_name);
+ return FALSE;
+ }
+
+ PROCESSENTRY32W pe;
+ pe.dwSize = sizeof(pe);
+
+ if (Process32FirstW(hSnap, &pe)) {
+ do {
+ DWORD procSessionId = 0;
+ if (ProcessIdToSessionId(pe.th32ProcessID, &procSessionId)) {
+ if (procSessionId == in_session_id) {
+ // jesli PID jest jednym z istotnych procesow systemowych - NIE UBIJAJ
+ if (CompareStringOrdinal(pe.szExeFile, -1, L"services.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"smss.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"wininit.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"lsass.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"csrss.exe", -1, TRUE) == CSTR_EQUAL)
+ {
+ continue;
+ }
+ *pid = pe.th32ProcessID;
+ StringCchCopyW(pid_exe_name, 64, pe.szExeFile);
+ processes_count++;
+ break;
+ }
+ }
+ } while (Process32NextW(hSnap, &pe));
+ }
+ if (processes_count > 1) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Odnaleziono %lu procesow.",
+ function_name,
+ processes_count
+ );
+ }
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Skorelowano sesje RDP z procesem: %s, PID: %lu, ID sesji RDP: %lu",
+ function_name,
+ pid_exe_name,
+ *pid,
+ in_session_id
+ );
+ return TRUE;
+}
+/*
+FIND_SESSION_STATUS find_remote_domain_user_session(PSID user_sid, PUNICODE_STRING domain_username, DWORD *out_session_id) {
+ PWTS_SESSION_INFO session_info = NULL;
+ DWORD session_count = 0;
+
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ if (!WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &session_info, &session_count)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad pobierania sesji WTSEnumerateSessions", function_name);
+ return FIND_SESSION_ERROR;
+ }
+
+ BOOL is_rdp_session_empty = TRUE;
+ for (int i = 0; i < MAX_RDP_SESSIONS; i++) {
+ if (remote_interactive_sessions[i].active) {
+ is_rdp_session_empty = FALSE;
+ }
+ }
+ WCHAR sid_string[128] = { 0 };
+ check_SID(user_sid, sid_string, ARRAYSIZE(sid_string));
+
+ if (!is_rdp_session_empty) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Wykryto istniejace sesje RDP...", function_name);
+ for (int i = 0; i < MAX_RDP_SESSIONS; i++) {
+ if (compare_unicode_with_wchar(domain_username, remote_interactive_sessions[i].domain_username)
+ && wcscmp(sid_string, remote_interactive_sessions[i].user_sid) == 0)
+ {
+
+ for (DWORD j = 0; j < session_count; j++) {
+ DWORD session_Id = session_info[j].SessionId;
+ USHORT* protocol = NULL;
+ DWORD bytesReturned = 0;
+
+ if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_Id, WTSClientProtocolType, (LPWSTR*)&protocol, &bytesReturned)) {
+ if (*protocol == WTS_PROTOCOL_RDP) {
+
+ WTS_CLIENT_ADDRESS* address_ptr = NULL;
+ if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_Id, WTSClientAddress, (LPWSTR*)&address_ptr, &bytesReturned)) {
+
+ WCHAR client_ip[INET_ADDRSTRLEN] = { 0 };
+
+ struct sockaddr_in sa;
+ ZeroMemory(&sa, sizeof(sa));
+ sa.sin_family = AF_INET;
+ CopyMemory(&sa.sin_addr, &address_ptr->Address[2], 4);
+
+ if (!InetNtopW(AF_INET, &sa.sin_addr, client_ip, INET_ADDRSTRLEN)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad konwersji IP w InetNtopW", function_name);
+ WTSFreeMemory(address_ptr);
+ WTSFreeMemory(protocol);
+ return FIND_SESSION_ERROR;
+ }
+ /*
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Przed konwersja IP...", function_name);
+
+
+ if (wcscmp(client_ip, remote_interactive_sessions[i].ip_address) != 0) {
+ WTSFreeMemory(address_ptr);
+ WTSFreeMemory(protocol);
+ return FIND_SESSION_ERROR;
+ }
+ /*log_line(LOG_TYPE_DEBUG,
+ L"[%s] Po konwersji IP...", function_name);
+
+ WCHAR user_name[64] = { 0 };
+ PWTSCLIENTW pClient = NULL;
+ DWORD bytes = 0;
+
+ if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_Id, WTSClientInfo, (LPWSTR*)&pClient, &bytes) && pClient) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Dla konta: %s, z IP: %s, SID: %s juz istnieje zapoczatkowana sesja RDP!",
+ function_name,
+ pClient->UserName,
+ client_ip,
+ sid_string);
+ WTSFreeMemory(pClient);
+ }
+ WTSFreeMemory(address_ptr);
+ WTSFreeMemory(protocol);
+
+ return FIND_SESSION_FOUND;
+ }
+ }
+ WTSFreeMemory(protocol);
+ }
+ }
+ }
+ }
+ }
+
+ for (DWORD i = 0; i < session_count; i++) {
+ DWORD session_Id = session_info[i].SessionId;
+
+ USHORT* protocol = NULL;
+ DWORD bytesReturned = 0;
+
+ if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_Id, WTSClientProtocolType, (LPWSTR*)&protocol, &bytesReturned)) {
+ if (*protocol == WTS_PROTOCOL_RDP) {
+ LPWSTR data_buffer = NULL;
+
+ WCHAR user_name[64] = { 0 };
+ WCHAR domain_name[64] = { 0 };
+ WCHAR client_name[64] = { 0 };
+ WCHAR protocol_type[16] = { 0 };
+ WCHAR client_ip[INET_ADDRSTRLEN] = { 0 };
+
+ WTS_CLIENT_ADDRESS* address_ptr = NULL;
+
+ copy_lpwstr_string(remote_protocol_type_to_string(*protocol), protocol_type, ARRAYSIZE(protocol_type));
+
+ retrieve_session_data(session_Id, WTSUserName, user_name, ARRAYSIZE(user_name));
+ retrieve_session_data(session_Id, WTSDomainName, domain_name, ARRAYSIZE(domain_name));
+ retrieve_session_data(session_Id, WTSClientName, client_name, ARRAYSIZE(client_name));
+
+ if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_Id, WTSClientAddress, (LPWSTR*)&address_ptr, &bytesReturned)) {
+ if (address_ptr->AddressFamily == AF_INET) {
+ struct sockaddr_in sa;
+ ZeroMemory(&sa, sizeof(sa));
+ sa.sin_family = AF_INET;
+ CopyMemory(&sa.sin_addr, &address_ptr->Address[2], 4);
+
+ if (!InetNtopW(AF_INET, &sa.sin_addr, client_ip, INET_ADDRSTRLEN)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad konwersji IP w InetNtopW", function_name);
+ WTSFreeMemory(protocol);
+ WTSFreeMemory(address_ptr);
+ return FIND_SESSION_ERROR;
+ }
+ }
+ WTSFreeMemory(address_ptr);
+ }
+
+ PWTSCLIENTW pClient = NULL;
+ DWORD bytes = 0;
+
+ if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_Id, WTSClientInfo, (LPWSTR*)&pClient, &bytes) && pClient) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Przechwycono sesje RemoteInteractive: Nazwa konta: %s, Domena: %s, Nazwa maszyny: %s, IP: %s, Protokol: %s",
+ function_name,
+ pClient->UserName,
+ pClient->Domain,
+ pClient->ClientName,
+ client_ip,
+ protocol_type);
+ }
+
+ for (int i = 0; i < MAX_RDP_SESSIONS; i++) {
+ if (!remote_interactive_sessions[i].active) {
+ remote_interactive_sessions[i].active = TRUE;
+ StringCchCopyW(remote_interactive_sessions[i].user_sid, ARRAYSIZE(remote_interactive_sessions[i].user_sid), sid_string);
+ StringCchCopyW(remote_interactive_sessions[i].domain_username, ARRAYSIZE(remote_interactive_sessions[i].domain_username), pClient->UserName);
+ StringCchCopyW(remote_interactive_sessions[i].ip_address, ARRAYSIZE(remote_interactive_sessions[i].ip_address), client_ip);
+
+ log_line(LOG_TYPE_DEBUG, L"[%s] Dodano sesje RDP do kolejki... Dane sesji: User SID: %s, Nazwa konta: %s, IP: %s",
+ function_name,
+ remote_interactive_sessions[i].user_sid,
+ remote_interactive_sessions[i].domain_username,
+ remote_interactive_sessions[i].ip_address);
+ WTSFreeMemory(pClient);
+ WTSFreeMemory(protocol);
+ WTSFreeMemory(session_info);
+
+ *out_session_id = session_Id;
+
+ return FIND_SESSION_NOT_FOUND;
+ }
+ }
+ WTSFreeMemory(pClient);
+ }
+ WTSFreeMemory(protocol);
+ }
+ }
+ WTSFreeMemory(session_info);
+ return FIND_SESSION_ERROR;
+}
+*/
+BOOL retrieve_session_data(DWORD session_id, WTS_INFO_CLASS info, WCHAR* out_buff, size_t out_size) {
+ LPWSTR data_buffer = NULL;
+ DWORD bytes_returned = 0;
+
+ if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, info, &data_buffer, &bytes_returned)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad przy pozyskiwaniu WTS_INFO_CLASS, kod: %lu...",
+ L"retrieve_session_data",
+ DWORD(info));
+ return FALSE;
+ }
+
+ if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, info, &data_buffer, &bytes_returned)) {
+ if (data_buffer != NULL && bytes_returned > sizeof(WCHAR)) {
+ copy_lpwstr_string(data_buffer, out_buff, out_size);
+ }
+ else {
+ copy_lpwstr_string((LPWSTR)NULL, out_buff, out_size);
+ }
+ WTSFreeMemory(data_buffer);
+ return TRUE;
+ }
+
+ copy_lpwstr_string((LPWSTR)NULL, out_buff, out_size);
+ return TRUE;
+}
+
+BOOL convert_ip_addr_to_string(WTS_CLIENT_ADDRESS *ip, WCHAR *ip_data) {
+ if (ip->AddressFamily == AF_INET) {
+ struct sockaddr_in sa;
+ ZeroMemory(&sa, sizeof(sa));
+ sa.sin_family = AF_INET;
+ CopyMemory(&sa.sin_addr, &ip->Address[2], 4);
+
+ if (!InetNtopW(AF_INET, &sa.sin_addr, ip_data, INET_ADDRSTRLEN)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad konwersji IP w InetNtopW", L"convert_ip_addr_to_string");
+ return FALSE;
+ }
+ }
+ else {
+ WCHAR buffer[512] = { 0 };
+ WCHAR temp[8];
+
+ for (int i = 0; i < 20; i++) {
+ StringCchPrintfW(temp, ARRAYSIZE(temp), L"%02X ", ip->Address[i]);
+ StringCchCatW(buffer, ARRAYSIZE(buffer), temp);
+ }
+
+ log_line(LOG_TYPE_WARNING, L"[%s] Nieobslugiwany format adresu, kod: %lu, zawartosc addressFamily: %s...",
+ L"convert_ip_addr_to_string",
+ ip->AddressFamily,
+ buffer);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+void print_kerberos_module_functions(HMODULE kerberos_module) {
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ BYTE* base_address = (BYTE*)kerberos_module;
+ IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)base_address;
+
+ if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
+ return;
+
+ IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)(base_address + dos_header->e_lfanew);
+ if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
+ return;
+
+ IMAGE_DATA_DIRECTORY exportDir = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+ if (exportDir.VirtualAddress == 0) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Brak eksportow w kerberos.dll",
+ function_name
+ );
+ return;
+ }
+ IMAGE_EXPORT_DIRECTORY* exportDirectory = (IMAGE_EXPORT_DIRECTORY*)(base_address + exportDir.VirtualAddress);
+
+ DWORD* namesRVA = (DWORD*)(base_address + exportDirectory->AddressOfNames);
+ WORD* ordinals = (WORD*)(base_address + exportDirectory->AddressOfNameOrdinals);
+ DWORD* functions = (DWORD*)(base_address + exportDirectory->AddressOfFunctions);
+
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Lista eksportowanych funkcji w kerberos.dll: ",
+ function_name
+ );
+
+ for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++) {
+ char* funcName = (char*)(base_address + namesRVA[i]);
+
+ WCHAR funcNameW[256];
+ MultiByteToWideChar(CP_ACP, 0, funcName, -1, funcNameW, ARRAYSIZE(funcNameW));
+
+ WORD ordinal = ordinals[i];
+ DWORD funcRVA = functions[ordinal];
+ void* funcAddress = base_address + funcRVA;
+
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] %s at ordinal %d, adres: %p",
+ function_name,
+ funcNameW,
+ ordinal + exportDirectory->Base,
+ funcAddress
+ );
+ }
+}
+
+void test_load_library(LPCWSTR dll_name, LPCWSTR rust_library) {
+ HMODULE h_lib = LoadLibraryW(dll_name);
+ if (h_lib) {
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Zaladowano modul DLL %s",
+ L"test_load_library",
+ dll_name
+ );
+ typedef int (*PFN_Run)();
+ PFN_Run pRun = (PFN_Run)GetProcAddress(h_lib, "Run");
+ if (pRun) {
+ int result = pRun();
+ log_line(LOG_TYPE_INFO,
+ L"[%s]rezultat z zaladowanej DLL: %d",
+ L"test_load_library",
+ result
+ );
+ }
+ FreeLibrary(h_lib);
+ }
+ else {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w LoadLibraryW: %lu", L"test_load_library", GetLastError());
+ }
+ HMODULE h_rust_lib = LoadLibraryW(rust_library);
+
+ if (h_rust_lib) {
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Zaladowano DLL stworzona w Rust %s",
+ L"test_load_library",
+ rust_library
+ );
+ typedef int (*PFN_Run)();
+ PFN_Run rust_run = (PFN_Run)GetProcAddress(h_rust_lib, "Run");
+ if (rust_run) {
+ int result = rust_run();
+ log_line(LOG_TYPE_INFO,
+ L"[%s]rezultat z biblioteki w Rust: %d",
+ L"test_load_library",
+ result
+ );
+ }
+ FreeLibrary(h_rust_lib);
+ }
+ else {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad w LoadLibraryW dla biblioteki Rust: %lu", L"test_load_library", GetLastError());
+ }
+}
+
+
+BOOL initialize_rdp_sessions_array() {
+ rdp_sessions.session_data = (RDP_SESSION_DATA*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ INITIAL_RDP_SESSIONS * sizeof(RDP_SESSION_DATA));
+
+ if (!rdp_sessions.session_data) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad alokacji pamieci dla sesji RDP", L"initialize_rdp_sessions_array");
+ return FALSE;
+ }
+
+ rdp_sessions.session_count = 0;
+ rdp_sessions.capacity = INITIAL_RDP_SESSIONS;
+
+ log_line(LOG_TYPE_INFO, L"[%s] Poprawnie zaalokowano pamiec dla sesji RDP...", L"initialize_rdp_sessions_array");
+
+ return TRUE;
+}
+
+void free_rdp_sessions_array() {
+ if (rdp_sessions.session_data) {
+ if (rdp_sessions.session_data->processes) {
+ HeapFree(GetProcessHeap(), 0, rdp_sessions.session_data->processes);
+ log_line(LOG_TYPE_INFO, L"[%s] Zwalnianie pamieci po sesjach RDP - procesy...", L"free_rdp_sessions_array");
+ }
+ HeapFree(GetProcessHeap(), 0, rdp_sessions.session_data);
+ log_line(LOG_TYPE_INFO, L"[%s] Zwalnianie pamieci po sesjach RDP...", L"free_rdp_sessions_array");
+ }
+ ZeroMemory(&rdp_sessions, sizeof(rdp_sessions));
+}
+
+MATCH_SESSION_STATUS match_existing_rdp_sessions(DWORD in_session_id, DWORD *out_session_id) {
+ WCHAR function_name[40] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ log_line(LOG_TYPE_INFO,
+ L"[%s] ilosc sesji RDP = %lu",
+ function_name,
+ rdp_sessions.session_count);
+
+ if (rdp_sessions.session_count == 0) {
+ //utworz nowa sesje
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Wykryto nowa sesje RDP - Brak aktywnych sesji RDP uzytkownikow domenowych, dodawanie nowej...",
+ function_name);
+ *out_session_id = in_session_id;
+
+ return SESSION_CREATE_NEW;
+ }
+ if (rdp_sessions.session_count != 0) {
+ for (DWORD i = 0; i < rdp_sessions.session_count; i++) {
+ RDP_SESSION_DATA* sess = &rdp_sessions.session_data[i];
+
+ /*
+ * w przypadku gdy id sesji zgadza sie z juz istniejaca :
+ * sprawdz czy jest valid - jesli jest valid, to znaczy ze MFA
+ * zostalo we wczesniejszej zaakceptowane i zaktualizuj proces wazny dla sesji RDP
+ * jesli nie zostalo zaakceptowane - ubij procesy
+ */
+
+ if (sess->session_id == in_session_id) {
+ *out_session_id = sess->session_id;
+ if (sess->valid) {
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Wykryto istniejaca sesje RDP, ID sesji = %lu, aktualizacja stanu polaczenia...",
+ function_name,
+ in_session_id);
+ return SESSION_UPDATE_EXISTING;
+ }
+ else {
+ /*
+ DWORD pid = 0;
+ WCHAR proc_name[128] = { 0 };
+
+ DWORD processes_count = 0;
+
+ HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (hSnap == INVALID_HANDLE_VALUE) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad CreateToolhelp32Snapshot", function_name);
+ //return FALSE;
+ }
+
+ PROCESSENTRY32W pe;
+ pe.dwSize = sizeof(pe);
+
+ if (Process32FirstW(hSnap, &pe)) {
+ do {
+ DWORD procSessionId = 0;
+ if (ProcessIdToSessionId(pe.th32ProcessID, &procSessionId)) {
+ if (procSessionId == in_session_id) {
+ // jesli PID jest jednym z istotnych procesow systemowych - NIE UBIJAJ
+ if (CompareStringOrdinal(pe.szExeFile, -1, L"services.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"smss.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"wininit.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"lsass.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"csrss.exe", -1, TRUE) == CSTR_EQUAL)
+ {
+ continue;
+ }
+ //processes_count++;
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Odnaleziono proces: %s, PID: %lu",
+ function_name,
+ pe.szExeFile,
+ pe.th32ProcessID
+ );
+ }
+ }
+ } while (Process32NextW(hSnap, &pe));
+ }
+ if (processes_count > 1) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Odnaleziono %lu procesow.",
+ function_name,
+ processes_count
+ );
+ }
+ */
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Sesja RDP ID = %lu juz istnieje i zostala odrzucona...",
+ function_name,
+ in_session_id);
+ return SESSION_TERMINATE_EXISTING;
+ }
+ }
+ }
+ }
+ log_line(LOG_TYPE_ERROR,
+ L"[%s] Wystapil blad sesji RDP, ID sesji: %lu, sesja o nieznanym statusie...",
+ function_name,
+ in_session_id);
+ return SESSION_STATUS_UNKNOWN;
+}
+
+BOOL create_new_rdp_session(PSID user_psid, DWORD session_id) {
+ WCHAR function_name[40] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ RDP_SESSION_DATA new_session = { 0 };
+
+ new_session.processes = (RELATED_PROCESSES*)HeapAlloc(
+ GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(RELATED_PROCESSES));
+
+ if (!new_session.processes) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad alokacji pamieci dla sesji RDP - alokacja danych procesu", function_name);
+ return FALSE;
+ }
+
+ new_session.processes->process = (RELATED_PROCESS*)HeapAlloc(
+ GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ INITIAL_PROCESSES_COUNT * sizeof(RELATED_PROCESS));
+ if (!new_session.processes->process) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad alokacji pamieci dla sesji RDP - alokacja danych PID", function_name);
+ HeapFree(GetProcessHeap(), 0, new_session.processes);
+ return FALSE;
+ }
+ new_session.processes->count = 0;
+
+ //log_line(LOG_TYPE_DEBUG, L"[%s] processes ptr: %p", function_name, new_session.processes);
+ //log_line(LOG_TYPE_DEBUG, L"[%s] processes->process ptr: %p", function_name, new_session.processes->process);
+ //log_line(LOG_TYPE_DEBUG, L"[%s] proc_name ptr: %p", function_name, proc_name);
+
+ if (!retrieve_rdp_session_info(session_id, &new_session, user_psid)) {
+ log_line(LOG_TYPE_ERROR,
+ L"[%s] Nie utworzono nowej sesji RDP...",
+ function_name);
+ return FALSE;
+ }
+
+ //zinkrementuj licznik sesji
+ rdp_sessions.session_count++;
+
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Przechwycono sesje %s -- SID konta: %s, IP maszyny: %s, Nazwa konta: %s, Nazwa DNS: %s, Nazwa klienta: %s, ID sesji: %lu",
+ function_name,
+ L"RemoteInteractive",
+ new_session.user_sid,
+ new_session.client_ip,
+ new_session.user_name,
+ new_session.domain_name,
+ new_session.client_name,
+ new_session.session_id
+ );
+
+ /*
+ * dane z sesji uzyskane - teraz czas na mfa
+ * najpierw przygotuj bufor JSON do wyslania do serwera
+ */
+
+ char buff[192] = { 0 };
+ format_data_for_connection(new_session.session_id, buff);
+ NTSTATUS mfa_result = manage_mfa_session(buff);
+
+ /*
+ * dalsza obsluga sesji zalezy od rezultatu mfa
+ * jesli nastapi zaakceptowanie polaczenia - ustaw flage valid na true
+ * ponadto - dodaj informacje o procesie ktory kontroluje RDP
+ * jesli nastapi odrzucenie w mfa - ustaw flage valid na false i ubij polaczenie i nie dodawaj sesji do listy
+ * kazdy status inny niz STATUS_SUCCESS (mozliwe jest np. zerwanie polaczenia w trakcie negocjacji tcp, blad w http, itp.
+ * powoduje zamkniecie sesji)
+ */
+
+ if (mfa_result != STATUS_SUCCESS) {
+ log_line(LOG_TYPE_ERROR,
+ L"[%s] MFA nie powiodlo sie, odrzucanie polaczenia...",
+ function_name);
+ new_session.valid = FALSE;
+ /*
+ if (get_PIDs_from_sessionID(session_id, new_session.processes, FALSE)) {
+ //terminate_remaining_processes(new_session.processes, session_id);
+ }*/
+ } else {
+ log_line(LOG_TYPE_ERROR,
+ L"[%s] MFA zaakceptowane, procedowanie polaczenia...",
+ function_name);
+ new_session.valid = TRUE;
+ }
+
+ if (get_PIDs_from_sessionID(session_id, new_session.processes, FALSE)) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Dodano procesy zwiazane z sesja RDP...",
+ function_name
+ );
+ }
+ /*
+ * Procesowanie sesji, dodaj sesje do listy
+ */
+ if (add_session_to_list(&new_session)) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Dodano poprawnie sesje do listy, ID sesji RDP = %lu...",
+ function_name,
+ new_session.session_id
+ );
+ }
+
+ return TRUE;
+}
+
+BOOL update_existing_rdp_session(DWORD session_id) {
+ WCHAR function_name[40] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ for (DWORD i = 0; i < rdp_sessions.session_count; i++) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Liczba sesji RDP: %lu",
+ function_name,
+ rdp_sessions.session_count
+ );
+ RDP_SESSION_DATA* sess = &rdp_sessions.session_data[i];
+ if (sess->session_id == session_id) {
+ /*
+ * sprawdzam czy dla sesji sa juz zarejestrowane procesy
+ */
+
+ if (get_PIDs_from_sessionID(session_id, sess->processes, TRUE))
+ {
+
+ }
+
+ if (!sess->valid) {
+ terminate_remaining_processes(sess->processes, session_id);
+ }
+ }
+ }
+ return TRUE;
+}
+
+BOOL terminate_remaining_processes(RELATED_PROCESSES* session_processes, DWORD sess_id) {
+ WCHAR function_name[40] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ /*
+ * zakoncz procesy dla danej sesji
+ */
+ if (session_processes->count != 0) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Konczenie procesow dla sesji o ID = %lu, ilosc procesow: %lu",
+ function_name,
+ sess_id,
+ session_processes->count
+ );
+ for (DWORD i = 0; i < session_processes->count; i++) {
+ RELATED_PROCESS proc = session_processes->process[i];
+ DWORD proc_id = proc.pid;
+ if (WTSTerminateProcess(WTS_CURRENT_SERVER_HANDLE, proc_id, 1)) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Zakonczono - %s -> PID: %lu",
+ function_name,
+ proc.process_name,
+ proc_id
+ );
+ }
+ else {
+ log_line(LOG_TYPE_ERROR,
+ L"[%s] Blad WTSTerminateProcess...",
+ function_name
+ );
+ return FALSE;
+ }
+ }
+ }
+ else {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Nie odnaleziono procesow dla sesji RDP o ID = %lu",
+ function_name
+ );
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL add_session_to_list(const RDP_SESSION_DATA *session) {
+ WCHAR function_name[40] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ if (!rdp_sessions.session_data) {
+ log_line(LOG_TYPE_ERROR,
+ L"[%s] Blad w dostepie do listy sesji RDP...",
+ function_name);
+ return FALSE;
+ }
+ if (rdp_sessions.session_count >= rdp_sessions.capacity) {
+ DWORD new_capacity = rdp_sessions.capacity * 2;
+ RDP_SESSION_DATA* resized = (RDP_SESSION_DATA*)HeapReAlloc(
+ GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ rdp_sessions.session_data,
+ new_capacity * sizeof(RDP_SESSION_DATA));
+ if (!resized) {
+ log_line(LOG_TYPE_ERROR,
+ L"[%s] Nie udalo sie zrealokowac pamieci, blad HeapReAlloc...",
+ function_name);
+ return FALSE;
+ }
+
+ rdp_sessions.session_data = resized;
+ rdp_sessions.capacity = new_capacity;
+ }
+
+ rdp_sessions.session_data[rdp_sessions.session_count++] = *session;
+
+ return TRUE;
+}
+
+BOOL remove_session_from_list(DWORD sess_id) {
+ WCHAR function_name[40] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ for (DWORD i = 0; i < rdp_sessions.session_count; i++) {
+ RDP_SESSION_DATA* sess = &rdp_sessions.session_data[i];
+ if (sess->session_id == sess_id) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Usuwanie sesji RDP: %lu z listy --> PSID: %s, IP: %s, Nazwa konta: %s...",
+ function_name,
+ sess_id,
+ sess->user_sid,
+ sess->client_ip,
+ sess->domain_name
+ );
+ if (!terminate_remaining_processes(sess->processes, sess_id)) {
+ return FALSE;
+ }
+
+ /*
+ * procesy ubite, wyczysc dane po sesji
+ */
+ if (sess->processes) {
+ if (sess->processes->process) {
+ log_line(LOG_TYPE_DEBUG, L"[%s] Wyczyszczono sess->processes->process...", function_name);
+ HeapFree(GetProcessHeap(), 0, sess->processes->process);
+ }
+ log_line(LOG_TYPE_DEBUG, L"[%s] Wyczyszczono sess->processes...", function_name);
+ HeapFree(GetProcessHeap(), 0, sess->processes);
+ }
+
+ rdp_sessions.session_count--;
+ break;
+ }
+ }
+ return TRUE;
+}
+
+BOOL retrieve_rdp_session_info(DWORD session_id, RDP_SESSION_DATA *session_data, PSID user_psid) {
+ WCHAR function_name[40] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ if (!session_data) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad przy pozyskiwaniu danych nowej sesji RDP...", function_name);
+ return FALSE;
+ }
+ //ZeroMemory(session_data, sizeof(RDP_SESSION_DATA));
+
+ DWORD bytesReturned = 0;
+
+ session_data->session_id = session_id;
+
+ session_data->protocol_type = WTS_PROTOCOL_RDP;
+
+ check_SID(user_psid, session_data->user_sid, ARRAYSIZE(session_data->user_sid));
+
+ if (!retrieve_session_data(session_id, WTSUserName, session_data->user_name, ARRAYSIZE(session_data->user_name)))
+ return FALSE;
+
+ if (!retrieve_session_data(session_id, WTSDomainName, session_data->domain_name, ARRAYSIZE(session_data->domain_name)))
+ return FALSE;
+
+ if (!retrieve_session_data(session_id, WTSClientName, session_data->client_name, ARRAYSIZE(session_data->client_name)))
+ return FALSE;
+
+ WTS_CLIENT_ADDRESS* address_ptr = NULL;
+ if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSClientAddress, (LPWSTR*)&address_ptr, &bytesReturned)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad przy pozyskiwaniu adresu IP...", function_name);
+ return FALSE;
+ }
+
+ if (!convert_ip_addr_to_string(address_ptr, session_data->client_ip))
+ return FALSE;
+
+
+ //kiedys trzeba dodac szersza obsluge Console
+
+ return TRUE;
+}
+
+void format_data_for_connection(DWORD session_id, char *buffer) {
+ char dns[64] = { 0 };
+ char user[64] = { 0 };
+ for (DWORD i = 0; i < rdp_sessions.session_count; i++) {
+ RDP_SESSION_DATA* sess = &rdp_sessions.session_data[i];
+ if (sess->session_id == session_id) {
+ WideCharToMultiByte(CP_UTF8, 0, sess->domain_name, -1, dns, sizeof(dns), NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, sess->user_name, -1, user, sizeof(user), NULL, NULL);
+ }
+ }
+ StringCchPrintfA(buffer, 192, "{\"Domena\":\"%s\",\"Nazwa konta\":\"%s\"}", dns, user);
+}
\ No newline at end of file
diff --git a/SSP_DLL/interprocessSSP.h b/SSP_DLL/interprocessSSP.h
new file mode 100644
index 0000000..ee2a029
--- /dev/null
+++ b/SSP_DLL/interprocessSSP.h
@@ -0,0 +1,115 @@
+#include "main.h"
+
+#include "utilsSSP.h"
+
+#include
+#include
+
+#include
+
+#define WTSUserSid ((WTS_INFO_CLASS)29)
+
+const int INITIAL_RDP_SESSIONS = 4;
+const int INITIAL_PROCESSES_COUNT = 5;
+
+typedef struct {
+ BOOL active;
+ WCHAR user_sid[128];
+ WCHAR ip_address[INET_ADDRSTRLEN];
+ WCHAR domain_username[64];
+} EXISTING_RDP_SESSION;
+
+typedef enum _FIND_SESSION_STATUS {
+ FIND_SESSION_ERROR = -1,
+ FIND_SESSION_NOT_FOUND = 0,
+ FIND_SESSION_FOUND = 1
+} FIND_SESSION_STATUS;
+
+typedef enum _MATCH_SESSION_STATUS {
+ SESSION_CREATE_NEW = 0,
+ SESSION_UPDATE_EXISTING = 1,
+ SESSION_TERMINATE_EXISTING = 2,
+
+ SESSION_STATUS_UNKNOWN = 98,
+ SESSION_UNINITALIZED = 99
+} MATCH_SESSION_STATUS;
+
+typedef struct _RELATED_PROCESS {
+ DWORD pid;
+ WCHAR process_name[128];
+} RELATED_PROCESS;
+
+typedef struct _RELATED_PROCESSES {
+ RELATED_PROCESS* process;
+ DWORD count;
+} RELATED_PROCESSES;
+
+typedef struct _RDP_SESSION_DATA {
+ DWORD session_id;
+ WCHAR user_name[64];
+ WCHAR user_sid[128];
+ WCHAR domain_name[64];
+ WCHAR client_name[64];
+ WCHAR client_ip[INET_ADDRSTRLEN];
+ USHORT protocol_type;
+ BOOL valid; //w przypadku gdy MFA zostanie odrzucone ustaw na FALSE
+ RELATED_PROCESSES* processes;
+} RDP_SESSION_DATA;
+
+typedef struct _RDP_SESSION_ARRAY {
+ RDP_SESSION_DATA* session_data;
+ DWORD capacity;
+ DWORD session_count;
+} RDP_SESSION_ARRAY;
+
+extern RDP_SESSION_ARRAY rdp_sessions;
+
+
+const int MAX_RDP_SESSIONS = 16;
+extern EXISTING_RDP_SESSION remote_interactive_sessions[MAX_RDP_SESSIONS];
+
+
+
+const LPCWSTR RublonUser2 = L"S-1-5-21-1865802264-3486384077-2187269939-1109"; // tylko do celow testowych - RublonUser2
+
+PSID convert_sidstring_to_sid(LPCWSTR sid_str = RublonUser2);
+
+void get_LUID_string(const PLUID luid, PWSTR out, size_t out_len);
+
+BOOL get_PIDs_from_sessionID(DWORD in_session_id, RELATED_PROCESSES* session_processes, BOOL update_flag);
+
+BOOL get_PID_from_SessionID(DWORD in_session_id, DWORD* pid, WCHAR* pid_exe_name);
+
+/* RDP SESSIONS */
+
+// do celow testowych
+//FIND_SESSION_STATUS find_remote_domain_user_session(PSID user_sid, PUNICODE_STRING domain_username, DWORD* out_session_id);
+
+BOOL retrieve_session_data(DWORD session_id, WTS_INFO_CLASS info, WCHAR* out_buff, size_t out_size);
+//RDP SESSIONS
+
+
+void print_kerberos_module_functions(HMODULE kerberos_module);
+
+void test_load_library(LPCWSTR dll_name, LPCWSTR rust_library);
+
+BOOL initialize_rdp_sessions_array();
+void free_rdp_sessions_array();
+
+BOOL create_new_rdp_session(PSID user_psid, DWORD session_id);
+
+BOOL update_existing_rdp_session(DWORD session_id);
+
+BOOL terminate_remaining_processes(RELATED_PROCESSES* session_processes, DWORD sess_id);
+
+BOOL add_session_to_list(const RDP_SESSION_DATA* session);
+
+BOOL remove_session_from_list(DWORD sess_id);
+
+MATCH_SESSION_STATUS match_existing_rdp_sessions(DWORD in_session_id, DWORD *out_session_id);
+
+BOOL retrieve_rdp_session_info(DWORD session_id, RDP_SESSION_DATA* session_data, PSID user_psid);
+
+BOOL convert_ip_addr_to_string(WTS_CLIENT_ADDRESS* ip, WCHAR* ip_data);
+
+void format_data_for_connection(DWORD session_id, char* buffer);
\ No newline at end of file
diff --git a/SSP_DLL/kerberos_lib.h b/SSP_DLL/kerberos_lib.h
new file mode 100644
index 0000000..3f59c93
--- /dev/null
+++ b/SSP_DLL/kerberos_lib.h
@@ -0,0 +1,2 @@
+#pragma once
+
diff --git a/SSP_DLL/main.h b/SSP_DLL/main.h
new file mode 100644
index 0000000..04fda97
--- /dev/null
+++ b/SSP_DLL/main.h
@@ -0,0 +1,37 @@
+#pragma once
+/*
+* =========== UWAGA !!!! =================
+* POD ZADNYM POZOREM NIE ZMIENIAC KOLEJNOSCI NAGLOWKOW ANI DEFINICJI MAKR
+* MA TO KLUCZOWE ZNACZENIE PODCZAS BUDOWANIA BIBLIOTEKI
+*
+*/
+#define WIN32_LEAN_AND_MEAN
+#define _WINSOCKAPI_
+
+#include
+#include
+
+#include
+#define SECURITY_WIN32
+#define CINTERFACE
+#define COBJMACROS
+
+typedef long NTSTATUS;
+
+#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
+#define STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L)
+#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
+//#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
+#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009AL)
+
+#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
+
+#include
+#include
+#include
+
+#include
+#include
+
+/***/
\ No newline at end of file
diff --git a/SSP_DLL/rublonLSA.cpp b/SSP_DLL/rublonLSA.cpp
new file mode 100644
index 0000000..e69de29
diff --git a/SSP_DLL/rublonSSP.cpp b/SSP_DLL/rublonSSP.cpp
new file mode 100644
index 0000000..4e870da
--- /dev/null
+++ b/SSP_DLL/rublonSSP.cpp
@@ -0,0 +1,630 @@
+#include "interprocessSSP.h"
+#include "connectorSSP.h"
+#include "domainUtilsSSP.h"
+#include "rublonSSP.h"
+
+#pragma warning(disable:4996)
+
+//#define PACKAGE_NAME "RublonSSP"
+
+void* trampoline = NULL;
+
+BYTE originalBytes[16] = { 0 };
+
+
+SECPKG_FUNCTION_TABLE Rublon_ssp_SPFunction_Table = {
+ .LogonUserEx2 = Rublon_ap_SpLogonUserEx2,
+ .Initialize = Rublon_ssp_SpInitialize,
+ .Shutdown = Rublon_ssp_SpShutDown,
+ .GetInfo = Rublon_ssp_SpGetInfo,
+ .AcceptCredentials = Rublon_ssp_SpAcceptCredentials,
+ .AcquireCredentialsHandle = Rublon_ssp_SpAcquireCredentialsHandle,
+ .InitLsaModeContext = Rublon_ssp_SpInitLsaModeContext,
+ .AcceptLsaModeContext = Rublon_ssp_SpAcceptLsaModeContext,
+};
+
+NTSTATUS NTAPI Rublon_ap_SpLogonUserEx2(
+ PLSA_CLIENT_REQUEST ClientRequest,
+ SECURITY_LOGON_TYPE LogonType,
+ PVOID ProtocolSubmitBuffer,
+ PVOID ClientBufferBase,
+ ULONG SubmitBufferSize,
+ PVOID* ProfileBuffer,
+ PULONG ProfileBufferSize,
+ PLUID LogonId,
+ PNTSTATUS SubStatus,
+ PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
+ PVOID* TokenInformation,
+ PUNICODE_STRING* AccountName,
+ PUNICODE_STRING* AuthenticatingAuthority,
+ PUNICODE_STRING* MachineName,
+ PSECPKG_PRIMARY_CRED PrimaryCredentials,
+ PSECPKG_SUPPLEMENTAL_CRED_ARRAY* SupplementalCredentials
+)
+{
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Wywolano SpLogonUserEx2...",
+ function_name
+ );
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI Rublon_ssp_SpInitialize(ULONG_PTR PackageId, PSECPKG_PARAMETERS Parameters, PLSA_SECPKG_FUNCTION_TABLE FunctionTable)
+{
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Wywolano SpInitialize...",
+ function_name
+ );
+
+ HMODULE kerberos_handle = GetModuleHandleW(L"kerberos.dll");
+ if (kerberos_handle != NULL) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] kerberos.dll jest zaladowany...",
+ function_name);
+ print_kerberos_module_functions(kerberos_handle);
+ FARPROC target_func = GetProcAddress(kerberos_handle, "KerbMakeKdcCall");
+
+ if (!target_func) {
+ log_line(LOG_TYPE_WARNING,
+ L"[%s] nie odnaleziono funkcji %s...",
+ function_name,
+ L"KerbMakeKdcCall");
+ }
+ Original_KerbMakeKdcCall = (KerbMakeKdcCall_t)target_func;
+
+ DWORD oldProtect;
+ BYTE trampoline[] = {
+ 0x49, 0xBB,
+ 0,0,0,0,0,0,0,0,
+ 0x41, 0xFF, 0xE3
+ };
+ void* hook_target = (void*)target_func;
+ CopyMemory(&trampoline[2], &Hooked_KerbMakeKdcCall, sizeof(void*));
+
+ if (VirtualProtect(hook_target, sizeof(trampoline), PAGE_EXECUTE_READWRITE, &oldProtect)) {
+ CopyMemory(hook_target, trampoline, sizeof(trampoline));
+ VirtualProtect(hook_target, sizeof(trampoline), oldProtect, &oldProtect);
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] HOOK zainstalowany...",
+ function_name);
+ }
+
+ }
+ else {
+ log_line(LOG_TYPE_WARNING,
+ L"[%s] kerberos.dll jest niezaladowany...",
+ function_name);
+ }
+
+ initialize_rdp_sessions_array();
+
+
+ ZeroMemory(remote_interactive_sessions, sizeof(remote_interactive_sessions));
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Zerowanie listy sesji RDP...",
+ function_name
+ );
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI Rublon_ssp_SpShutDown(void)
+{
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+ if (domain_info.domain_SID) {
+ log_line(LOG_TYPE_INFO, L"[%s] %s", function_name,
+ L"Zwalnianie pamieci Domain SID..."
+ );
+ LocalFree(domain_info.domain_SID);
+ }
+ if (domain_users) {
+ HANDLE hHeap = GetProcessHeap();
+ log_line(LOG_TYPE_INFO, L"[%s] %s", function_name,
+ L"Zwalnianie pamieci USER_INFO..."
+ );
+ HeapFree(hHeap, 0, domain_users);
+ }
+ log_line(LOG_TYPE_INFO,
+ L"[%s] %s%s",
+ function_name,
+ L"Zamykanie pliku log i sesji...\n",
+ L"=================================================================\n"
+ );
+ if (log_file) {
+ CloseHandle(log_file);
+ log_file = NULL;
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI Rublon_ssp_SpGetInfo(PSecPkgInfoW PackageInfo)
+{
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Wywolano SpGetInfo...",
+ function_name
+ );
+
+ SEC_WCHAR piname[] = L"RublonSSP";
+ SEC_WCHAR picomment[] = L"Rublon Security Support Provider";
+ PackageInfo->fCapabilities =
+ SECPKG_FLAG_INTEGRITY |
+ SECPKG_FLAG_PRIVACY |
+ SECPKG_FLAG_CONNECTION |
+ SECPKG_FLAG_NEGOTIABLE |
+ SECPKG_FLAG_MULTI_REQUIRED |
+ SECPKG_FLAG_ACCEPT_WIN32_NAME |
+ SECPKG_FLAG_LOGON |
+ SECPKG_FLAG_EXTENDED_ERROR;
+ PackageInfo->wVersion = 1;
+ PackageInfo->wRPCID = SECPKG_ID_NONE;
+ PackageInfo->cbMaxToken = 0;
+ PackageInfo->Name = piname;
+ PackageInfo->Comment = picomment;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI Rublon_ssp_SpAcceptCredentials(SECURITY_LOGON_TYPE LogonType, PUNICODE_STRING AccountName, PSECPKG_PRIMARY_CRED PrimaryCredentials, PSECPKG_SUPPLEMENTAL_CRED SupplementalCredentials)
+{
+ NTSTATUS result = STATUS_UNSUCCESSFUL;
+ WCHAR function_name[40] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ if (!g_logfile_lock_initialized) {
+ init_logfile_lock();
+ }
+
+ if (LogonType == RemoteInteractive) {
+ PWTS_SESSION_INFO session_info = NULL;
+ DWORD session_count = 0;
+
+ DWORD rdp_session_id = 0;
+
+ if (!WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &session_info, &session_count)) {
+ log_line(LOG_TYPE_ERROR, L"[%s] Blad pobierania sesji WTSEnumerateSessions", function_name);
+ return STATUS_ACCESS_DENIED;
+ }
+
+ MATCH_SESSION_STATUS stat = SESSION_UNINITALIZED;
+
+ for (DWORD i = 0; i < session_count; i++) {
+ DWORD id = session_info[i].SessionId;
+
+ USHORT* protocol = NULL;
+ DWORD bytesReturned = 0;
+
+ if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, id, WTSClientProtocolType, (LPWSTR*)&protocol, &bytesReturned)) {
+ if (*protocol == WTS_PROTOCOL_RDP) {
+ stat = match_existing_rdp_sessions(id, &rdp_session_id);
+ }
+ WTSFreeMemory(protocol);
+ }
+ }
+
+ if (stat == SESSION_CREATE_NEW) {
+ if (create_new_rdp_session(PrimaryCredentials->UserSid, rdp_session_id))
+ return STATUS_SUCCESS;
+ }
+ if (stat == SESSION_UPDATE_EXISTING) {
+ if (update_existing_rdp_session(rdp_session_id)) {
+
+ }
+ }
+ if (stat == SESSION_TERMINATE_EXISTING) {
+ if (remove_session_from_list(rdp_session_id)) {
+
+ }
+ }
+
+ }
+ PSID rublon_user_2 = convert_sidstring_to_sid();
+
+ /*
+ PCWSTR logon_type_str = L"";
+ if(LogonType < LOGON_TYPE_COUNT) {
+ logon_type_str = W_LOGON_TYPE_STRINGS[LogonType];
+ }
+
+ WCHAR sid_string[128] = { 0 };
+ WCHAR luid_string[128] = { 0 };
+ check_SID(PrimaryCredentials->UserSid, sid_string, ARRAYSIZE(sid_string));
+ get_LUID_string(&PrimaryCredentials->LogonId, luid_string, ARRAYSIZE(luid_string));
+
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Logon Type: %s, Logon ID: %s, PSID: %s, Nazwa konta: %s, Nazwa domeny: %s, Nazwa DNS: %s, SupCred->PackageName :%s",
+ function_name,
+ logon_type_str,
+ luid_string,
+ sid_string,
+ check_unicode_string(AccountName),
+ check_unicode_string(&PrimaryCredentials->DomainName),
+ check_unicode_string(&PrimaryCredentials->DnsDomainName),
+ check_unicode_string(&SupplementalCredentials->PackageName)
+ );
+
+
+ if (LogonType == RemoteInteractive) {
+ //find_remote_domain_user_session();
+ DWORD session_id = { 0 };
+
+ if (find_remote_domain_user_session(PrimaryCredentials->UserSid, AccountName, &session_id) == FIND_SESSION_NOT_FOUND) {
+ DWORD pid = 0;
+ WCHAR proc_name[64] = { 0 };
+ HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (hSnap == INVALID_HANDLE_VALUE) return 0;
+
+ PROCESSENTRY32W pe;
+ pe.dwSize = sizeof(pe);
+
+ if (Process32FirstW(hSnap, &pe)) {
+ do {
+ DWORD procSessionId = 0;
+ if (ProcessIdToSessionId(pe.th32ProcessID, &procSessionId)) {
+ if (procSessionId == session_id) {
+
+ if (CompareStringOrdinal(pe.szExeFile, -1, L"services.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"smss.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"wininit.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"lsass.exe", -1, TRUE) == CSTR_EQUAL ||
+ CompareStringOrdinal(pe.szExeFile, -1, L"csrss.exe", -1, TRUE) == CSTR_EQUAL)
+ {
+ continue;
+ }
+ pid = pe.th32ProcessID;
+ StringCchCopyW(proc_name, 64, pe.szExeFile);
+ break;
+ }
+ }
+ } while (Process32NextW(hSnap, &pe));
+ }
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Skorelowano sesje RDP z procesem: %s, PID: %lu, w sesji: %lu",
+ function_name,
+ proc_name,
+ pid,
+ session_id
+ );
+
+ CloseHandle(hSnap);
+ WCHAR wDNS[64] = { 0 };
+ char DNS[64] = { 0 };
+
+ WCHAR wUser[64] = { 0 };
+ char User[64] = { 0 };
+
+ StringCchCopyW(wDNS, 64, PrimaryCredentials->DnsDomainName.Buffer);
+ WideCharToMultiByte(CP_ACP, 0, wDNS, -1, DNS, 64, NULL, NULL);
+
+ StringCchCopyW(wUser, 64, AccountName->Buffer);
+ WideCharToMultiByte(CP_ACP, 0, wUser, -1, User, 64, NULL, NULL);
+
+ char buff[192];
+ StringCchPrintfA(buff, sizeof(buff), "{\"Domena\":\"%s\",\"Nazwa konta\":\"%s\"}", DNS, User);
+
+ result = manage_mfa_session(buff);
+
+ if (result != STATUS_SUCCESS) {
+ //WTSTerminateProcess(WTS_CURRENT_SERVER_HANDLE, 999, 1);
+
+ log_line(LOG_TYPE_ERROR,
+ L"[%s] MFA nie powiodlo sie, odrzucanie polaczenia...",
+ function_name);
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Ubijanie procesu %lu...",
+ function_name,
+ pid
+ );
+ WTSTerminateProcess(WTS_CURRENT_SERVER_HANDLE, pid, 1);
+ return STATUS_ACCESS_DENIED;
+ }
+ }
+ }
+ */
+ if (LogonType == Network || LogonType == NetworkCleartext) {
+ //testowy scenariusz gdy logowanie jest od RublonUser2
+ if (EqualSid(PrimaryCredentials->UserSid, rublon_user_2)) {
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] PSID sa identyczne",
+ function_name
+ );
+ //test_load_library(L"C:\\AdditionalDLL.dll", L"C:\\rust_ssp_lib.dll");
+ //retrieve_current_logon_sessions();
+ //result = manage_mfa_session(u8"{\"organizacja\":\"Rublon\",\"login\":\"Adrian\",\"haslo\":\"bezpieczne_haslo_321\"}");
+ /*
+ DWORD pids[32];
+ DWORD proc_id = get_PID_from_PSID(rublon_user_2, pids, ARRAYSIZE(pids));
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Odnaleziono %05u PID dla uzytkownika.",
+ function_name,
+ proc_id
+ );
+ if (proc_id != NULL) {
+ for(DWORD i = 0; i < proc_id; i++)
+ list_net_connections_by_PID(pids[i]);
+ }*/
+ }
+ }
+
+ LocalFree(rublon_user_2);
+
+ return result;
+}
+
+NTSTATUS NTAPI Rublon_ssp_SpAcquireCredentialsHandle(
+ PUNICODE_STRING PrincipalName,
+ ULONG CredentialUseFlags,
+ PLUID LogonId,
+ PVOID AuthorizationData,
+ PVOID GetKeyFn,
+ PVOID GetKeyArgument,
+ PLSA_SEC_HANDLE CredentialHandle,
+ PTimeStamp ExpirationTime
+) {
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Wywolano SpAcquireCredentialsHandle...",
+ function_name
+ );
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI Rublon_ssp_SpInitLsaModeContext(
+ LSA_SEC_HANDLE CredentialHandle,
+ LSA_SEC_HANDLE ContextHandle,
+ PUNICODE_STRING TargetName,
+ ULONG ContextRequirements,
+ ULONG TargetDataRep,
+ PSecBufferDesc InputBuffers,
+ PLSA_SEC_HANDLE NewContextHandle,
+ PSecBufferDesc OutputBuffers,
+ PULONG ContextAttributes,
+ PTimeStamp ExpirationTime,
+ PBOOLEAN MappedContext,
+ PSecBuffer ContextData
+) {
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Wywolano SpInitLsaModeContext...",
+ function_name
+ );
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI Rublon_ssp_SpAcceptLsaModeContext(
+ LSA_SEC_HANDLE CredentialHandle,
+ LSA_SEC_HANDLE ContextHandle,
+ PSecBufferDesc InputBuffer,
+ ULONG ContextRequirements,
+ ULONG TargetDataRep,
+ PLSA_SEC_HANDLE NewContextHandle,
+ PSecBufferDesc OutputBuffer,
+ PULONG ContextAttributes,
+ PTimeStamp ExpirationTime,
+ PBOOLEAN MappedContext,
+ PSecBuffer ContextData
+) {
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Wywolano SpAcceptLsaModeContext...",
+ function_name
+ );
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI Rublon_ssp_SpAcceptSecurityContext(
+ LSA_SEC_HANDLE CredentialHandle,
+ LSA_SEC_HANDLE ContextHandle,
+ PSecBufferDesc InputBuffer,
+ ULONG ContextRequirements,
+ ULONG TargetDataRep,
+ PLSA_SEC_HANDLE NewContextHandle,
+ PSecBufferDesc OutputBuffer,
+ PULONG ContextAttributes,
+ PTimeStamp ExpirationTime,
+ PBOOLEAN MappedContext,
+ PSecBuffer ContextData
+)
+{
+
+ if (!InputBuffer || !InputBuffer->pBuffers) return STATUS_INVALID_PARAMETER;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI Rublon_ssp_SpLsaModeInitialize(_In_ ULONG LsaVersion, PULONG PackageVersion, PSECPKG_FUNCTION_TABLE* ppTables, PULONG pcTables)
+{
+ create_log_file(rublon_log_filepath);
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Wywolano SpLsaModeInitialize...",
+ function_name
+ );
+
+ // TODO: dodac obsulge co w przypadku fail
+ // czy odlaczenie dll'ki od procesu?...
+
+ HRESULT res = get_domain_info();
+ if (SUCCEEDED(res)) {
+ domain_info.initialized = TRUE;
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Status maszyny: Nazwa DNS domeny: %s, Nazwa NetBIOS: %s, Czy w domenie: %s, Czy kontroler domeny: %s",
+ function_name,
+ domain_info.DNS_domain_name,
+ domain_info.NetBIOS_name,
+ (domain_info.is_machine_domain_joined) ? L"TAK" : L"NIE",
+ (domain_info.is_domain_controller) ? L"TAK" : L"NIE"
+ );
+ }
+ else if (res == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) {
+ log_line(LOG_TYPE_WARNING,
+ L"[%s] RPC niedostepny, uruchamiam monitor...",
+ function_name);
+ if (InterlockedCompareExchange(&domain_monitor_thread_counter, 1, 0) == 0) {
+ HANDLE hThread = CreateThread(NULL, 0, run_dc_monitor, NULL, 0, NULL);
+ if (hThread) CloseHandle(hThread);
+ }
+ }
+ else {
+ log_line(LOG_TYPE_ERROR,
+ L"[%s] Nie mozna pobrac danych do ustalenia statusu DC: 0x%08X",
+ function_name,
+ res);
+ }
+
+ *PackageVersion = SECPKG_INTERFACE_VERSION;
+ // *ppTables = Rublon_ssp_SecPkgFunctionTable;
+ // *pcTables = ARRAYSIZE(Rublon_ssp_SecPkgFunctionTable);
+
+ *ppTables = &Rublon_ssp_SPFunction_Table;
+ *pcTables = 1;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI Rublon_ssp_LsaApInitializePackage(
+ ULONG AuthenticationPackageId,
+ PLSA_DISPATCH_TABLE LsaDispatchTable,
+ PSTRING Database,
+ PSTRING Confidentiality,
+ PSTRING* PackageName
+) {
+ /*
+ static STRING name = { sizeof(PACKAGE_NAME) - 2, sizeof(PACKAGE_NAME), (PCHAR)PACKAGE_NAME };
+ *PackageName = &name;
+ send_to_interprocess_pipe("[LSA] Wywolano LsaApInitializePackage...\n");
+ */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI Rublon_ssp_LsaApLogonUser(
+ PLSA_CLIENT_REQUEST ClientRequest,
+ SECURITY_LOGON_TYPE LogonType,
+ PVOID ProtocolSubmitBuffer,
+ PVOID ClientBufferBase,
+ ULONG SubmitBufferLength,
+ PVOID* ProfileBuffer,
+ PULONG ProfileBufferLength,
+ PLUID LogonId,
+ PNTSTATUS SubStatus,
+ PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
+ PVOID* TokenInformation,
+ PLSA_UNICODE_STRING* AccountName,
+ PLSA_UNICODE_STRING* AuthenticatingAuthority
+) {
+
+ send_to_interprocess_pipe("[LSA] Wywolano LsaApLogonUser...\n");
+ *SubStatus = 0;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS NTAPI Rublon_ssp_LsaApLogonUserEx(
+ PLSA_CLIENT_REQUEST ClientRequest,
+ SECURITY_LOGON_TYPE LogonType,
+ PVOID ProtocolSubmitBuffer,
+ PVOID* ProfileBuffer,
+ PULONG ProfileBufferLength,
+ PLUID LogonId,
+ PNTSTATUS SubStatus,
+ PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
+ PVOID* TokenInformation,
+ PUNICODE_STRING* AccountName,
+ PUNICODE_STRING* AuthenticatingAuthority
+)
+{
+ WCHAR logLine[MAX_LOG_LINE] = { 0 };
+ char logonTypeStr[64];
+ wsprintfA(logonTypeStr, "LogonType = %d", LogonType);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS WINAPI Hooked_KerbMakeKdcCall(PVOID a, PVOID b, PVOID c) {
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Wywolano shookowany KerbMakeKdcCall...",
+ L"HOOK"
+ );
+
+ // jakakolwiek logika dzialania...
+
+ return Original_KerbMakeKdcCall(a, b, c);
+}
+
+void HookFunction_x64(void* targetFunc, void* hookFunc) {
+ DWORD oldProtect;
+
+
+ memcpy(originalBytes, targetFunc, 12);
+
+
+ trampoline = VirtualAlloc(NULL, 32, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ if (!trampoline) {
+ printf("VirtualAlloc failed\n");
+ return;
+ }
+
+ memcpy(trampoline, originalBytes, 12);
+
+ BYTE* tramp = (BYTE*)trampoline;
+ uintptr_t origFuncRest = (uintptr_t)targetFunc + 12;
+
+ tramp[12] = 0xE9;
+
+ INT32 relOffset = (INT32)(origFuncRest - ((uintptr_t)tramp + 12 + 5));
+ memcpy(tramp + 13, &relOffset, sizeof(relOffset));
+
+
+ VirtualProtect(targetFunc, 12, PAGE_EXECUTE_READWRITE, &oldProtect);
+
+ BYTE patch[12];
+
+ patch[0] = 0x48;
+ patch[1] = 0xB8;
+ uintptr_t hookAddr = (uintptr_t)hookFunc;
+ memcpy(patch + 2, &hookAddr, sizeof(hookAddr));
+
+ patch[10] = 0xFF;
+ patch[11] = 0xE0;
+
+
+ memcpy(targetFunc, patch, 12);
+
+
+ VirtualProtect(targetFunc, 12, oldProtect, &oldProtect);
+
+
+ FlushInstructionCache(GetCurrentProcess(), targetFunc, 12);
+
+
+ Original_KerbMakeKdcCall = (KerbMakeKdcCall_t)trampoline;
+
+ printf("Hook zainstalowany pod adresem: %p\n", targetFunc);
+}
+
+void UnhookFunction_x64(void* targetFunc) {
+ DWORD oldProtect;
+ VirtualProtect(targetFunc, 12, PAGE_EXECUTE_READWRITE, &oldProtect);
+ CopyMemory(targetFunc, originalBytes, 12);
+ VirtualProtect(targetFunc, 12, oldProtect, &oldProtect);
+ FlushInstructionCache(GetCurrentProcess(), targetFunc, 12);
+
+ if (trampoline) {
+ VirtualFree(trampoline, 0, MEM_RELEASE);
+ trampoline = NULL;
+ }
+
+ printf("Hook usuniety\n");
+}
+
diff --git a/SSP_DLL/rublonSSP.h b/SSP_DLL/rublonSSP.h
new file mode 100644
index 0000000..3916a51
--- /dev/null
+++ b/SSP_DLL/rublonSSP.h
@@ -0,0 +1,147 @@
+#include "utilsSSP.h"
+
+typedef NTSTATUS(WINAPI* KerbMakeKdcCall_t)(PVOID a, PVOID b, PVOID c);
+
+KerbMakeKdcCall_t Original_KerbMakeKdcCall = NULL;
+
+NTSTATUS NTAPI Rublon_ap_SpLogonUserEx2(
+ PLSA_CLIENT_REQUEST ClientRequest,
+ SECURITY_LOGON_TYPE LogonType,
+ PVOID ProtocolSubmitBuffer,
+ PVOID ClientBufferBase,
+ ULONG SubmitBufferSize,
+ PVOID* ProfileBuffer,
+ PULONG ProfileBufferSize,
+ PLUID LogonId,
+ PNTSTATUS SubStatus,
+ PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
+ PVOID* TokenInformation,
+ PUNICODE_STRING* AccountName,
+ PUNICODE_STRING* AuthenticatingAuthority,
+ PUNICODE_STRING* MachineName,
+ PSECPKG_PRIMARY_CRED PrimaryCredentials,
+ PSECPKG_SUPPLEMENTAL_CRED_ARRAY* SupplementalCredentials
+);
+
+
+NTSTATUS NTAPI Rublon_ssp_SpLsaModeInitialize(
+ ULONG LsaVersion,
+ PULONG PackageVersion,
+ PSECPKG_FUNCTION_TABLE* ppTables,
+ PULONG pcTables
+);
+
+NTSTATUS NTAPI Rublon_ssp_SpInitialize(
+ ULONG_PTR PackageId,
+ PSECPKG_PARAMETERS Parameters,
+ PLSA_SECPKG_FUNCTION_TABLE FunctionTable
+);
+
+NTSTATUS NTAPI Rublon_ssp_SpGetInfo(
+ PSecPkgInfoW PackageInfo
+);
+
+NTSTATUS NTAPI Rublon_ssp_SpShutDown(
+ void
+);
+
+NTSTATUS NTAPI Rublon_ssp_SpAcceptSecurityContext(
+ LSA_SEC_HANDLE CredentialHandle,
+ LSA_SEC_HANDLE ContextHandle,
+ PSecBufferDesc InputBuffer,
+ ULONG ContextRequirements,
+ ULONG TargetDataRep,
+ PLSA_SEC_HANDLE NewContextHandle,
+ PSecBufferDesc OutputBuffer,
+ PULONG ContextAttributes,
+ PTimeStamp ExpirationTime,
+ PBOOLEAN MappedContext,
+ PSecBuffer ContextData
+);
+
+NTSTATUS NTAPI Rublon_ssp_SpAcceptCredentials(
+ SECURITY_LOGON_TYPE LogonType,
+ PUNICODE_STRING AccountName,
+ PSECPKG_PRIMARY_CRED PrimaryCredentials,
+ PSECPKG_SUPPLEMENTAL_CRED SupplementalCredentials
+);
+
+NTSTATUS NTAPI Rublon_ssp_SpAcquireCredentialsHandle(
+ PUNICODE_STRING PrincipalName,
+ ULONG CredentialUseFlags,
+ PLUID LogonId,
+ PVOID AuthorizationData,
+ PVOID GetKeyFn,
+ PVOID GetKeyArgument,
+ PLSA_SEC_HANDLE CredentialHandle,
+ PTimeStamp ExpirationTime
+);
+
+NTSTATUS NTAPI Rublon_ssp_SpInitLsaModeContext(
+ LSA_SEC_HANDLE CredentialHandle,
+ LSA_SEC_HANDLE ContextHandle,
+ PUNICODE_STRING TargetName,
+ ULONG ContextRequirements,
+ ULONG TargetDataRep,
+ PSecBufferDesc InputBuffers,
+ PLSA_SEC_HANDLE NewContextHandle,
+ PSecBufferDesc OutputBuffers,
+ PULONG ContextAttributes,
+ PTimeStamp ExpirationTime,
+ PBOOLEAN MappedContext,
+ PSecBuffer ContextData
+);
+
+NTSTATUS NTAPI Rublon_ssp_SpAcceptLsaModeContext(
+ LSA_SEC_HANDLE CredentialHandle,
+ LSA_SEC_HANDLE ContextHandle,
+ PSecBufferDesc InputBuffer,
+ ULONG ContextRequirements,
+ ULONG TargetDataRep,
+ PLSA_SEC_HANDLE NewContextHandle,
+ PSecBufferDesc OutputBuffer,
+ PULONG ContextAttributes,
+ PTimeStamp ExpirationTime,
+ PBOOLEAN MappedContext,
+ PSecBuffer ContextData
+);
+
+NTSTATUS NTAPI Rublon_ssp_LsaApLogonUserEx(
+ PLSA_CLIENT_REQUEST ClientRequest,
+ SECURITY_LOGON_TYPE LogonType,
+ PVOID ProtocolSubmitBuffer,
+ PVOID* ProfileBuffer,
+ PULONG ProfileBufferLength,
+ PLUID LogonId,
+ PNTSTATUS SubStatus,
+ PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
+ PVOID* TokenInformation,
+ PUNICODE_STRING* AccountName,
+ PUNICODE_STRING* AuthenticatingAuthority
+);
+
+NTSTATUS NTAPI Rublon_ssp_LsaApLogonUser(
+ PLSA_CLIENT_REQUEST ClientRequest,
+ SECURITY_LOGON_TYPE LogonType,
+ PVOID ProtocolSubmitBuffer,
+ PVOID ClientBufferBase,
+ ULONG SubmitBufferLength,
+ PVOID* ProfileBuffer,
+ PULONG ProfileBufferLength,
+ PLUID LogonId,
+ PNTSTATUS SubStatus,
+ PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
+ PVOID* TokenInformation,
+ PLSA_UNICODE_STRING* AccountName,
+ PLSA_UNICODE_STRING* AuthenticatingAuthority
+);
+
+NTSTATUS NTAPI Rublon_ssp_LsaApInitializePackage(
+ ULONG AuthenticationPackageId,
+ PLSA_DISPATCH_TABLE LsaDispatchTable,
+ PSTRING Database,
+ PSTRING Confidentiality,
+ PSTRING* PackageName
+);
+
+NTSTATUS WINAPI Hooked_KerbMakeKdcCall(PVOID a, PVOID b, PVOID c);
\ No newline at end of file
diff --git a/SSP_DLL/rublonssp.def b/SSP_DLL/rublonssp.def
new file mode 100644
index 0000000..f8f9965
--- /dev/null
+++ b/SSP_DLL/rublonssp.def
@@ -0,0 +1,15 @@
+LIBRARY "RublonSSP"
+EXPORTS
+ SpLsaModeInitialize = Rublon_ssp_SpLsaModeInitialize
+ SpInitialize = Rublon_ssp_SpInitialize
+ SpGetInfo = Rublon_ssp_SpGetInfo
+ SpShutDown = Rublon_ssp_SpShutDown
+
+ SpAcquireCredentialsHandle = Rublon_ssp_SpAcquireCredentialsHandle
+
+ SpInitLsaModeContext = Rublon_ssp_SpInitLsaModeContext
+ SpAcceptLsaModeContext = Rublon_ssp_SpAcceptLsaModeContext
+
+ LsaApLogonUserEx2 = Rublon_ap_SpLogonUserEx2
+
+ LsaApInitializePackage = Rublon_ssp_LsaApInitializePackage
\ No newline at end of file
diff --git a/SSP_DLL/utilsSSP.cpp b/SSP_DLL/utilsSSP.cpp
new file mode 100644
index 0000000..7b0057d
--- /dev/null
+++ b/SSP_DLL/utilsSSP.cpp
@@ -0,0 +1,247 @@
+#include "utilsSSP.h"
+
+const char* LOG_TYPE_STRINGS[LOG_TYPE_COUNT] = {
+ "INFO",
+ "WARNING",
+ "ERROR",
+ "DEBUG"
+};
+
+PCWSTR W_LOG_TYPE_STRINGS[LOG_TYPE_COUNT] = {
+ L"INFO",
+ L"WARNING",
+ L"ERROR",
+ L"DEBUG"
+};
+
+//mapowanie nazw ze struktury SECURITY_LOGON_TYPE
+const char* LOGON_TYPE_STRINGS[] = {
+ "UndefinedLogonType",
+ "UnknownLogonType1",
+ "Interactive",
+ "Network",
+ "Batch",
+ "Service",
+ "Proxy",
+ "Unlock",
+ "NetworkCleartext",
+ "NewCredentials",
+ "RemoteInteractive",
+ "CachedInteractive",
+ "CachedRemoteInteractive",
+ "CachedUnlock"
+};
+
+PCWSTR W_LOGON_TYPE_STRINGS[] = {
+ L"UndefinedLogonType",
+ L"UnknownLogonType1",
+ L"Interactive",
+ L"Network",
+ L"Batch",
+ L"Service",
+ L"Proxy",
+ L"Unlock",
+ L"NetworkCleartext",
+ L"NewCredentials",
+ L"RemoteInteractive",
+ L"CachedInteractive",
+ L"CachedRemoteInteractive",
+ L"CachedUnlock"
+};
+
+HANDLE log_file = NULL;
+BOOL g_logfile_lock_initialized = FALSE;
+
+CRITICAL_SECTION g_logfile_lock;
+
+const WCHAR rublon_log_filepath[] = L"C:\\RublonSSP.log";
+
+#ifdef _DEBUG
+void send_to_interprocess_pipe(const char* msg) {
+ HANDLE hPipe = CreateFileA(
+ "\\\\.\\pipe\\sspmonitor",
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if (hPipe != INVALID_HANDLE_VALUE) {
+ DWORD bytesWritten;
+ WriteFile(hPipe, msg, (DWORD)strlen(msg), &bytesWritten, NULL);
+ CloseHandle(hPipe);
+ }
+}
+#endif //_DEBUG
+
+void init_logfile_lock() {
+ if (!g_logfile_lock_initialized) {
+ InitializeCriticalSection(&g_logfile_lock);
+ g_logfile_lock_initialized = TRUE;
+ }
+}
+
+BOOL create_log_file(LPCWSTR log_filename) {
+ if (log_file != NULL && log_file != INVALID_HANDLE_VALUE) {
+ return TRUE;
+ }
+ bool if_new_file = GetFileAttributesW(log_filename) == INVALID_FILE_ATTRIBUTES;
+
+ log_file = CreateFileW(log_filename, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (log_file == INVALID_HANDLE_VALUE) {
+ log_file = NULL;
+ return FALSE;
+ }
+ if (if_new_file) {
+ WORD bom = 0xFEFF;
+ DWORD written;
+ WriteFile(log_file, &bom, sizeof(bom), &written, NULL);
+ }
+
+ WCHAR function_name[64] = { 0 };
+ MultiByteToWideChar(CP_ACP, 0, __FUNCTION__, -1, function_name, ARRAYSIZE(function_name));
+
+ log_line(LOG_TYPE_INFO,
+ L"[%s] Utworzono plik log: %s",
+ function_name,
+ log_filename
+ );
+
+ get_process_details();
+ return TRUE;
+}
+
+void log_line(LOG_TYPE msg_type, PCWSTR msg_fmt, ...) {
+ SYSTEMTIME st;
+ WCHAR date_type_buff[128] = { 0 };
+ WCHAR var_args[896] = { 0 };
+ WCHAR log_buff[MAX_LOG_LINE] = { 0 };
+
+ GetLocalTime(&st);
+
+ StringCchPrintfW(date_type_buff, ARRAYSIZE(date_type_buff),
+ L"[%s][%04d-%02d-%02d %02d:%02d:%02d.%03d]",
+ W_LOG_TYPE_STRINGS[msg_type],
+ st.wYear, st.wMonth, st.wDay,
+ st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+ /*
+ wsprintfW(date_type_buff,
+ L"[%s][%04d-%02d-%02d %02d:%02d:%02d.%03d] ",
+ W_LOG_TYPE_STRINGS[msg_type],
+ st.wYear, st.wMonth, st.wDay,
+ st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);*/
+
+ va_list args;
+ va_start(args, msg_fmt);
+ StringCchVPrintfW(var_args, ARRAYSIZE(var_args), msg_fmt, args);
+ va_end(args);
+
+ StringCchPrintfW(log_buff, ARRAYSIZE(log_buff), L"%s%s\r\n", date_type_buff, var_args);
+
+ DWORD written = 0;
+ WriteFile(log_file, log_buff, lstrlenW(log_buff) * sizeof(WCHAR), &written, NULL);
+}
+
+
+void get_process_details() {
+ WCHAR buff[256] = { 0 };
+ DWORD pid = GetCurrentProcessId();
+ WCHAR path[MAX_PATH];
+
+ if (!GetModuleFileNameW(NULL, path, MAX_PATH))
+ {
+ lstrcpyW(path, L"");
+ }
+
+ wsprintfW(buff, L"PID procesu: %lu, Sciezka do pliku: %s", pid, path);
+ log_line(LOG_TYPE_INFO, L"%s", buff);
+}
+
+PCWSTR check_unicode_string(PUNICODE_STRING u_str) {
+ return (u_str && u_str->Buffer && u_str->Length > 0) ? u_str->Buffer : L"";
+}
+
+LPCWSTR check_string(LPCWSTR str) {
+ return (str != NULL && *str != L'\0') ? str : L"";
+}
+
+BOOL compare_unicode_with_wchar(PUNICODE_STRING u_str, WCHAR* name) {
+ if (!u_str || !u_str->Buffer || !name)
+ return FALSE;
+
+ size_t unicode_str_len = u_str->Length / sizeof(WCHAR);
+ const WCHAR* ptr1 = u_str->Buffer;
+ const WCHAR* ptr2 = name;
+
+ //log_line(LOG_TYPE_DEBUG, L"[%s] str1 = %s, str2 = %s", L"compare_unicode_with_wchar", u_str->Buffer, name);
+ size_t name_len = 0;
+ if (!SUCCEEDED(StringCchLengthW(name, STRSAFE_MAX_CCH, &name_len)))
+ return FALSE;
+
+ if (unicode_str_len != name_len)
+ return FALSE;
+
+ for (size_t i = 0; i < unicode_str_len; i++) {
+ if (ptr1[i] != ptr2[i]) {
+ //log_line(LOG_TYPE_DEBUG, L"[%s] Porownywane ciagi znakow sa rozne...", L"compare_unicode_with_wchar");
+ return FALSE;
+ }
+ }
+ /*
+ log_line(LOG_TYPE_DEBUG,
+ L"[%s] Porownywane ciagi znakow sa identyczne...", L"compare_unicode_with_wchar");
+ */
+ return TRUE;
+}
+
+void copy_lpwstr_string(LPWSTR in, WCHAR* out, size_t out_size) {
+ if (out == NULL || out_size == 0)
+ return;
+ if (in != NULL && *in != L'\0') {
+ StringCchCopyW(out, out_size, in);
+ }
+ else {
+ StringCchCopyW(out, out_size, L"");
+ }
+}
+
+void copy_lpwstr_string(LPCWSTR in, WCHAR* out, size_t out_size) {
+ if (out == NULL || out_size == 0)
+ return;
+ if (in != NULL && *in != L'\0') {
+ StringCchCopyW(out, out_size, in);
+ }
+ else {
+ StringCchCopyW(out, out_size, L"");
+ }
+}
+
+void check_SID(PSID psid, PWSTR out_buff, size_t out_buff_size) {
+ if (!psid || !IsValidSid(psid)) {
+ StringCchCopyW(out_buff, out_buff_size, L"");
+ return;
+ }
+ LPWSTR sid_string = nullptr;
+ if (ConvertSidToStringSidW(psid, &sid_string)) {
+ StringCchCopyW(out_buff, out_buff_size, sid_string);
+ LocalFree(sid_string);
+ }
+ else {
+ StringCchCopyW(out_buff, out_buff_size, L"");
+ }
+}
+
+LPCWSTR remote_protocol_type_to_string(USHORT proto) {
+ switch (proto) {
+ case WTS_PROTOCOL_CONSOLE:
+ return L"Console";
+ case WTS_PROTOCOL_SHADOW:
+ return L"Shadow";
+ case WTS_PROTOCOL_RDP:
+ return L"RDP";
+ default:
+ return L"";
+ }
+}
diff --git a/SSP_DLL/utilsSSP.h b/SSP_DLL/utilsSSP.h
new file mode 100644
index 0000000..1b24e79
--- /dev/null
+++ b/SSP_DLL/utilsSSP.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "main.h"
+
+#include
+
+constexpr int MAX_LOG_LINE = 2048;
+
+constexpr size_t LOGON_TYPE_COUNT = 14;
+
+typedef enum _LOG_TYPE {
+ LOG_TYPE_INFO = 0,
+ LOG_TYPE_WARNING,
+ LOG_TYPE_ERROR,
+ LOG_TYPE_DEBUG,
+ LOG_TYPE_COUNT
+} LOG_TYPE;
+
+typedef enum _WTS_PROTOCOL_TYPE {
+ WTS_PROTOCOL_CONSOLE = 0,
+ WTS_PROTOCOL_SHADOW = 1,
+ WTS_PROTOCOL_RDP = 2,
+ WTS_PROTOCOL_OTHER = 99
+} WTS_PROTOCOL_TYPE;
+
+extern const char* LOG_TYPE_STRINGS[LOG_TYPE_COUNT];
+extern PCWSTR W_LOG_TYPE_STRINGS[LOG_TYPE_COUNT];
+
+extern const char* LOGON_TYPE_STRINGS[LOGON_TYPE_COUNT];
+extern PCWSTR W_LOGON_TYPE_STRINGS[LOGON_TYPE_COUNT];
+
+extern HANDLE log_file;
+extern BOOL g_logfile_lock_initialized;
+extern CRITICAL_SECTION g_logfile_lock;
+extern const WCHAR rublon_log_filepath[];
+
+#ifdef _DEBUG
+ void send_to_interprocess_pipe(const char* msg);
+#else
+ #define send_to_interprocess_pipe(x) ((void)0)
+#endif //_DEBUG
+
+void init_logfile_lock();
+
+BOOL create_log_file(LPCWSTR log_filename);
+void log_line(LOG_TYPE msg_type, PCWSTR msg_fmt, ...);
+
+void get_process_details();
+
+PCWSTR check_unicode_string(PUNICODE_STRING u_str);
+LPCWSTR check_string(LPCWSTR str);
+
+BOOL compare_unicode_with_wchar(PUNICODE_STRING u_str, WCHAR *name);
+
+void copy_lpwstr_string(LPWSTR in, WCHAR *out, size_t out_size);
+void copy_lpwstr_string(LPCWSTR in, WCHAR *out, size_t out_size);
+
+void check_SID(PSID psid, PWSTR out_buff, size_t out_buff_size);
+
+LPCWSTR remote_protocol_type_to_string(USHORT proto);
\ No newline at end of file