From 5f6c6b2c29bda684f85a2201154c0d98af8ec150 Mon Sep 17 00:00:00 2001 From: DavidXanatos <3890945+DavidXanatos@users.noreply.github.com> Date: Sat, 11 May 2024 22:04:19 +0200 Subject: [PATCH] 1.14.0 --- Sandboxie/common/rc4.c | 110 ++++++++++++++++++ Sandboxie/core/dll/net.c | 31 ++++- Sandboxie/core/svc/SboxSvc.vcxproj | 10 ++ Sandboxie/core/svc/SboxSvc.vcxproj.filters | 3 + Sandboxie/core/svc/includes.cpp | 2 + Sandboxie/core/svc/msgids.h | 3 + Sandboxie/core/svc/sbieiniserver.cpp | 41 +++++++ Sandboxie/core/svc/sbieiniserver.h | 2 + Sandboxie/core/svc/sbieiniwire.h | 23 ++++ SandboxiePlus/QSbieAPI/SbieAPI.cpp | 21 ++++ SandboxiePlus/QSbieAPI/SbieAPI.h | 2 + .../SandMan/Windows/OptionsNetwork.cpp | 14 ++- 12 files changed, 260 insertions(+), 2 deletions(-) create mode 100644 Sandboxie/common/rc4.c diff --git a/Sandboxie/common/rc4.c b/Sandboxie/common/rc4.c new file mode 100644 index 00000000..b39ff8dd --- /dev/null +++ b/Sandboxie/common/rc4.c @@ -0,0 +1,110 @@ +/* + * Copyright 2024 David Xanatos, xanasoft.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +//--------------------------------------------------------------------------- +// Simple INSECURE Encryption Functions +//--------------------------------------------------------------------------- + + +#ifdef RC4_HEADER_ONLY + + +//--------------------------------------------------------------------------- +// Functions +//--------------------------------------------------------------------------- + + +#ifdef __cplusplus +extern "C" { +#endif + +void rc4_crypt(const unsigned char *key_ptr, unsigned int key_len, unsigned int stream_pos, unsigned char *buffer_ptr, unsigned int buffer_len); + +#ifdef __cplusplus +} // extern "C" +#endif + + +//--------------------------------------------------------------------------- +// Body +//--------------------------------------------------------------------------- + + +#else RC4_HEADER_ONLY + +typedef struct rc4_sbox_s +{ + unsigned char state[256]; + unsigned int x; + unsigned int y; +} rc4_sbox_t; + +void rc4_swap(unsigned char &a, unsigned char &b) +{ + unsigned char c = a; + a = b; + b = c; +} + +void rc4_init(rc4_sbox_t *rc4_sbox, const unsigned char *key_ptr, unsigned int key_len) +{ + rc4_sbox->x = 0; + rc4_sbox->y = 0; + + // Initialisation of the permutation + unsigned int i; + for (i = 0; i < 256; i++) + rc4_sbox->state[i] = (char)i; + + // Mixing permutation + unsigned int j = 0; + unsigned int k; + for (i = 0; i < 256; i++) + { + k = i % key_len; + + j = (key_ptr[k] + rc4_sbox->state[i] + j) & 0xff; + rc4_swap(rc4_sbox->state[i], rc4_sbox->state[j]); + } +} + +void rc4_transform(rc4_sbox_t *rc4_sbox, unsigned char *buffer_ptr, unsigned int buffer_len) +{ + unsigned int i; + for (i = 0; i < buffer_len; i++) + { + // The pseudo-random generation algorithm + rc4_sbox->x = (rc4_sbox->x + 1) & 0xff; + rc4_sbox->y = (rc4_sbox->y + rc4_sbox->state[rc4_sbox->x]) & 0xff; + rc4_swap(rc4_sbox->state[rc4_sbox->x], rc4_sbox->state[rc4_sbox->y]); + unsigned char keyChar = rc4_sbox->state[(rc4_sbox->state[rc4_sbox->x] + rc4_sbox->state[rc4_sbox->y]) & 0xff]; + + if (buffer_ptr) // NULL when seeking + buffer_ptr[i] ^= keyChar; + } +} + +void rc4_crypt(const unsigned char* key_ptr, unsigned int key_len, unsigned int stream_pos, unsigned char* buffer_ptr, unsigned int buffer_len) +{ + rc4_sbox_s sbox; + rc4_init(&sbox, key_ptr, key_len); + if(stream_pos) // RC4 is very insecure but the first few kb are espetially insecure + rc4_transform(&sbox, NULL, stream_pos); + rc4_transform(&sbox, buffer_ptr, buffer_len); +} + +#endif RC4_HEADER_ONLY \ No newline at end of file diff --git a/Sandboxie/core/dll/net.c b/Sandboxie/core/dll/net.c index 3440d712..532cd85c 100644 --- a/Sandboxie/core/dll/net.c +++ b/Sandboxie/core/dll/net.c @@ -31,6 +31,8 @@ #include "common/map.h" #include "common/str_util.h" #include "wsa_defs.h" +#include "core/svc/sbieiniwire.h" +#include "common/base64.c" //--------------------------------------------------------------------------- @@ -1245,12 +1247,39 @@ BOOLEAN WSA_ParseNetProxy(NETPROXY_RULE* proxy, const WCHAR* found_value) WCHAR* pass_value; ULONG pass_len; - if (SbieDll_FindTagValuePtr(found_value, L"Password", &pass_value, &pass_len, L'=', L';')) { + BOOLEAN ok = SbieDll_FindTagValuePtr(found_value, L"Password", &pass_value, &pass_len, L'=', L';'); + if (ok) { if (pass_len > 255) return FALSE; wmemcpy(proxy->pass, pass_value, pass_len); proxy->pass[pass_len] = L'\0'; } + else { + ok = SbieDll_FindTagValuePtr(found_value, L"EncryptedPW", &pass_value, &pass_len, L'=', L';'); + if (ok) { + + SBIE_INI_RC4_CRYPT_REQ req; + SBIE_INI_RC4_CRYPT_RPL *rpl; + + req.h.length = sizeof(SBIE_INI_RC4_CRYPT_REQ) + 255; + req.h.msgid = MSGID_SBIE_INI_RC4_CRYPT; + req.value_len = b64_decoded_size(pass_value); + b64_decode(pass_value, req.value, req.value_len); + + rpl = (SBIE_INI_RC4_CRYPT_RPL *)SbieDll_CallServer(&req.h); + if (rpl){ + + pass_len = rpl->value_len / sizeof(wchar_t); + if (pass_len > 255) + return FALSE; + wmemcpy(proxy->pass, rpl->value, pass_len); + proxy->pass[pass_len] = L'\0'; + + Dll_Free(rpl); + } + } + } + return TRUE; } diff --git a/Sandboxie/core/svc/SboxSvc.vcxproj b/Sandboxie/core/svc/SboxSvc.vcxproj index fece0fcb..96e56de7 100644 --- a/Sandboxie/core/svc/SboxSvc.vcxproj +++ b/Sandboxie/core/svc/SboxSvc.vcxproj @@ -373,6 +373,16 @@ true true + + true + true + true + true + true + true + true + true + true true diff --git a/Sandboxie/core/svc/SboxSvc.vcxproj.filters b/Sandboxie/core/svc/SboxSvc.vcxproj.filters index 7f9cdb74..dacf74ec 100644 --- a/Sandboxie/core/svc/SboxSvc.vcxproj.filters +++ b/Sandboxie/core/svc/SboxSvc.vcxproj.filters @@ -84,6 +84,9 @@ MountManager + + common + diff --git a/Sandboxie/core/svc/includes.cpp b/Sandboxie/core/svc/includes.cpp index 2a1223a5..e96d7d03 100644 --- a/Sandboxie/core/svc/includes.cpp +++ b/Sandboxie/core/svc/includes.cpp @@ -39,6 +39,8 @@ extern "C" { #define CRC_WITH_ADLER32 #include "common/crc.c" +#include "common/rc4.c" + #define PATTERN XPATTERN #include "common/pattern.c" diff --git a/Sandboxie/core/svc/msgids.h b/Sandboxie/core/svc/msgids.h index f84465b3..1cc16131 100644 --- a/Sandboxie/core/svc/msgids.h +++ b/Sandboxie/core/svc/msgids.h @@ -100,6 +100,9 @@ #define MSGID_SBIE_INI_GET_VERSION 0x18AA #define MSGID_SBIE_INI_GET_WAIT_HANDLE 0x18AB #define MSGID_SBIE_INI_RUN_SBIE_CTRL 0x180A +#define MSGID_SBIE_INI_RC4_CRYPT 0x180F + +//#define MSGID_SBIE_MGR 0x1900 #define MSGID_NETAPI 0x1A00 #define MSGID_NETAPI_USE_ADD 0x1A01 diff --git a/Sandboxie/core/svc/sbieiniserver.cpp b/Sandboxie/core/svc/sbieiniserver.cpp index 31d0e37d..bdaae16d 100644 --- a/Sandboxie/core/svc/sbieiniserver.cpp +++ b/Sandboxie/core/svc/sbieiniserver.cpp @@ -33,6 +33,9 @@ #include "common/my_version.h" #define CRC_HEADER_ONLY #include "common/crc.c" +#define RC4_HEADER_ONLY +#include "common/rc4.c" +#include "core/drv/api_defs.h" #ifdef NEW_INI_MODE extern "C" { @@ -147,6 +150,11 @@ MSG_HEADER *SbieIniServer::Handler2(MSG_HEADER *msg) return RunSbieCtrl(msg, idProcess, NT_SUCCESS(status)); } + if (msg->msgid == MSGID_SBIE_INI_RC4_CRYPT) { + + return RC4Crypt(msg, idProcess, NT_SUCCESS(status)); + } + if (NT_SUCCESS(status)) // if sandboxed return SHORT_REPLY(STATUS_NOT_SUPPORTED); @@ -2392,3 +2400,36 @@ MSG_HEADER *SbieIniServer::RunSbieCtrl(MSG_HEADER *msg, HANDLE idProcess, bool i return SHORT_REPLY(status); } + + +//--------------------------------------------------------------------------- +// RC4Crypt +//--------------------------------------------------------------------------- + + +MSG_HEADER *SbieIniServer::RC4Crypt(MSG_HEADER *msg, HANDLE idProcess, bool isSandboxed) +{ + SBIE_INI_RC4_CRYPT_REQ *req = (SBIE_INI_RC4_CRYPT_REQ *)msg; + if (req->h.length < sizeof(SBIE_INI_RC4_CRYPT_REQ)) + return SHORT_REPLY(STATUS_INVALID_PARAMETER); + + ULONG rpl_len = sizeof(SBIE_INI_RC4_CRYPT_RPL) + req->value_len; + SBIE_INI_RC4_CRYPT_RPL *rpl = (SBIE_INI_RC4_CRYPT_RPL *)LONG_REPLY(rpl_len); + if (!rpl) + return SHORT_REPLY(STATUS_INSUFFICIENT_RESOURCES); + + rpl->value_len = req->value_len; + memcpy(rpl->value, req->value, req->value_len); + + ULONG64 RandID = 0; + SbieApi_Call(API_GET_SECURE_PARAM, 3, L"RandID", (ULONG_PTR)&RandID, sizeof(RandID)); + if (RandID == 0) { + srand(GetTickCount()); + RandID = ULONG64(rand() & 0xFFFF) | (ULONG64(rand() & 0xFFFF) << 16) | (ULONG64(rand() & 0xFFFF) << 32) | (ULONG64(rand() & 0xFFFF) << 48); + SbieApi_Call(API_SET_SECURE_PARAM, 3, L"RandID", (ULONG_PTR)&RandID, sizeof(RandID)); + } + + rc4_crypt((BYTE*)&RandID, sizeof(RandID), 0x1000, rpl->value, rpl->value_len); + + return (MSG_HEADER*)rpl; +} \ No newline at end of file diff --git a/Sandboxie/core/svc/sbieiniserver.h b/Sandboxie/core/svc/sbieiniserver.h index f45141d6..bba3ec02 100644 --- a/Sandboxie/core/svc/sbieiniserver.h +++ b/Sandboxie/core/svc/sbieiniserver.h @@ -105,6 +105,8 @@ protected: MSG_HEADER *RunSbieCtrl(MSG_HEADER *msg, HANDLE idProcess, bool isSandboxed); + MSG_HEADER *RC4Crypt(MSG_HEADER *msg, HANDLE idProcess, bool isSandboxed); + protected: diff --git a/Sandboxie/core/svc/sbieiniwire.h b/Sandboxie/core/svc/sbieiniwire.h index 86ddc5a1..94308de1 100644 --- a/Sandboxie/core/svc/sbieiniwire.h +++ b/Sandboxie/core/svc/sbieiniwire.h @@ -174,6 +174,29 @@ struct tagSBIE_INI_PASSWORD_REQ typedef struct tagSBIE_INI_PASSWORD_REQ SBIE_INI_PASSWORD_REQ; +//--------------------------------------------------------------------------- +// rc4 Crypt +//--------------------------------------------------------------------------- + + +struct tagSBIE_INI_RC4_CRYPT_REQ +{ + MSG_HEADER h; + ULONG value_len; + UCHAR value[1]; +}; + +struct tagSBIE_INI_RC4_CRYPT_RPL +{ + MSG_HEADER h; + ULONG value_len; + UCHAR value[1]; +}; + +typedef struct tagSBIE_INI_RC4_CRYPT_REQ SBIE_INI_RC4_CRYPT_REQ; +typedef struct tagSBIE_INI_RC4_CRYPT_RPL SBIE_INI_RC4_CRYPT_RPL; + + //--------------------------------------------------------------------------- diff --git a/SandboxiePlus/QSbieAPI/SbieAPI.cpp b/SandboxiePlus/QSbieAPI/SbieAPI.cpp index 8974e888..69f23dd4 100644 --- a/SandboxiePlus/QSbieAPI/SbieAPI.cpp +++ b/SandboxiePlus/QSbieAPI/SbieAPI.cpp @@ -2150,6 +2150,27 @@ void CSbieAPI::ClearPassword() m->Password.clear(); } +SB_RESULT(QByteArray) CSbieAPI::RC4Crypt(const QByteArray& Data) +{ + ULONG req_len = sizeof(SBIE_INI_RC4_CRYPT_REQ) + Data.size(); + SScoped req(malloc(req_len)); + + req->h.length = req_len; + req->h.msgid = MSGID_SBIE_INI_RC4_CRYPT; + req->value_len = Data.size(); + memcpy(req->value, Data.constData(), req->value_len); + + SScoped rpl; + SB_STATUS Status = CallServer(&req->h, &rpl); + if (!Status) + return Status; + if (!rpl) + return SB_ERR(ERROR_SERVER_DISABLED); + if (rpl->h.status != 0) + return SB_ERR(rpl->h.status); + return CSbieResult(QByteArray((char*)rpl->value, rpl->value_len)); +} + bool CSbieAPI::GetDriverInfo(quint32 InfoClass, void* pBuffer, size_t Size) { __declspec(align(8)) ULONG64 parms[API_NUM_ARGS]; diff --git a/SandboxiePlus/QSbieAPI/SbieAPI.h b/SandboxiePlus/QSbieAPI/SbieAPI.h index 9287befa..bb0b4fe6 100644 --- a/SandboxiePlus/QSbieAPI/SbieAPI.h +++ b/SandboxiePlus/QSbieAPI/SbieAPI.h @@ -108,6 +108,8 @@ public: virtual SB_STATUS LockConfig(const QString& NewPassword); virtual void ClearPassword(); + virtual SB_RESULT(QByteArray) RC4Crypt(const QByteArray& Data); + virtual bool GetDriverInfo(quint32 InfoClass, void* pBuffer, size_t Size); enum EFeatureFlags diff --git a/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp b/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp index 86bb7a5e..fcb1d919 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp @@ -986,6 +986,12 @@ void COptionsWindow::ParseAndAddNetProxy(const QString& Value, bool disabled, co pItem->setData(4, Qt::UserRole, Login); QString Pass = Tags.value("password"); + if(Pass.isEmpty()) { + Pass = Tags.value("encryptedpw"); + auto res = theAPI->RC4Crypt(QByteArray::fromBase64(Pass.toLatin1())); + if (!res.IsError()) + Pass = QString::fromWCharArray((wchar_t*)res.GetValue().data(), res.GetValue().length() / sizeof(wchar_t)); + } if (Pass.length() > 255) Pass = Pass.left(255); pItem->setText(5, Pass); pItem->setData(5, Qt::UserRole, Pass); @@ -1024,7 +1030,13 @@ void COptionsWindow::SaveNetProxy() Tags.append("Port=" + Port); if (!Auth.isEmpty()) Tags.append("Auth=" + Auth); if (!Login.isEmpty()) Tags.append("Login=" + Login); - if (!Pass.isEmpty()) Tags.append("Password=" + Pass); + if (!Pass.isEmpty()) { + auto res = theAPI->RC4Crypt(QByteArray((char*)Pass.toStdWString().c_str(), Pass.length() * sizeof(wchar_t))); + if(res.IsError()) + Tags.append("Password=" + Pass); + else + Tags.append("EncryptedPW=" + res.GetValue().toBase64(QByteArray::OmitTrailingEquals)); + } QString Entry = Tags.join(";").prepend(Program + ","); if (pItem->checkState(0) == Qt::Checked)