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)