Add project files.

This commit is contained in:
EarthQuake
2020-04-17 19:03:33 +01:00
parent a6c9436854
commit 8eefabcc81
29 changed files with 3544 additions and 0 deletions
Binary file not shown.
+47
View File
@@ -0,0 +1,47 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SocksOverRDP-Plugin", "SocksOverRDP-Plugin\SocksOverRDP-Plugin.vcxproj", "{9402DF45-A060-4881-9F64-D16E094B97A7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SocksOverRDP-PluginPS", "SocksOverRDP-Plugin\SocksOverRDP-PluginPS.vcxproj", "{15DEE2D8-6972-49C0-9369-35730A29A2CF}"
ProjectSection(ProjectDependencies) = postProject
{9402DF45-A060-4881-9F64-D16E094B97A7} = {9402DF45-A060-4881-9F64-D16E094B97A7}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SocksOverRDP-Server", "SocksOverRDP-Server\SocksOverRDP-Server.vcxproj", "{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}"
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
{9402DF45-A060-4881-9F64-D16E094B97A7}.Debug|x64.ActiveCfg = Debug|x64
{9402DF45-A060-4881-9F64-D16E094B97A7}.Debug|x64.Build.0 = Debug|x64
{9402DF45-A060-4881-9F64-D16E094B97A7}.Debug|x86.ActiveCfg = Debug|Win32
{9402DF45-A060-4881-9F64-D16E094B97A7}.Debug|x86.Build.0 = Debug|Win32
{9402DF45-A060-4881-9F64-D16E094B97A7}.Release|x64.ActiveCfg = Release|x64
{9402DF45-A060-4881-9F64-D16E094B97A7}.Release|x64.Build.0 = Release|x64
{9402DF45-A060-4881-9F64-D16E094B97A7}.Release|x86.ActiveCfg = Release|Win32
{9402DF45-A060-4881-9F64-D16E094B97A7}.Release|x86.Build.0 = Release|Win32
{15DEE2D8-6972-49C0-9369-35730A29A2CF}.Debug|x64.ActiveCfg = Debug|x64
{15DEE2D8-6972-49C0-9369-35730A29A2CF}.Debug|x86.ActiveCfg = Debug|Win32
{15DEE2D8-6972-49C0-9369-35730A29A2CF}.Release|x64.ActiveCfg = Release|x64
{15DEE2D8-6972-49C0-9369-35730A29A2CF}.Release|x86.ActiveCfg = Release|Win32
{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Debug|x64.ActiveCfg = Debug|x64
{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Debug|x64.Build.0 = Debug|x64
{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Debug|x86.ActiveCfg = Debug|Win32
{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Debug|x86.Build.0 = Debug|Win32
{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Release|x64.ActiveCfg = Release|x64
{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Release|x64.Build.0 = Release|x64
{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Release|x86.ActiveCfg = Release|Win32
{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+19
View File
@@ -0,0 +1,19 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by SocksOverRDP-Plugin.rc
//
#define IDS_PROJNAME 100
#define IDR_SocksOverRDPPLUGIN 101
#define IDR_SocksOverRDPCLIENTPLUGIN 102
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 201
#define _APS_NEXT_COMMAND_VALUE 32768
#define _APS_NEXT_CONTROL_VALUE 201
#define _APS_NEXT_SYMED_VALUE 106
#endif
#endif
+897
View File
@@ -0,0 +1,897 @@
/*
* MIT License
*
* Copyright(c) 2020 Balazs Bucsay
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "stdafx.h"
#include "resource.h"
#include "SocksOverRDP-Plugin.h"
#pragma comment(lib, "Ws2_32.lib")
#define SocksOverRDP_CHANNEL_NAME "SocksChannel"
#define BUF_SIZE 4096
struct arguments {
DWORD enabled;
WCHAR *ip;
WCHAR *port;
};
// main thread struct for global variables
struct threadargs {
struct arguments *running_args;
SOCKET sockserver;
BOOL run;
IWTSVirtualChannel *m_ptrChannel = NULL;
HANDLE hThread = NULL;
} ta;
struct threads
{
DWORD dwThreadId;
HANDLE hThread;
BOOL run;
SOCKET s;
struct threads *next;
};
// debug verbose flag
static BOOL bVerbose = FALSE;
static struct threads *ThreadHead = NULL;
char szOverflow[BUF_SIZE * 4];
DWORD dwOverflow = 0;
static HANDLE ghMutex, ghLLMutex;
using namespace ATL;
#define CHECK_QUIT_HR( _x_ ) if(FAILED(hr)) { return hr; }
class ATL_NO_VTABLE SocksOverRDPPlugin :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<SocksOverRDPPlugin, &CLSID_CompReg>,
public IWTSPlugin,
public IWTSVirtualChannelCallback,
public IWTSListenerCallback
{
public:
CComPtr<IWTSVirtualChannel> m_ptrChannel;
DECLARE_REGISTRY_RESOURCEID(IDR_SocksOverRDPPLUGIN)
BEGIN_COM_MAP(SocksOverRDPPlugin)
COM_INTERFACE_ENTRY(IWTSPlugin)
COM_INTERFACE_ENTRY(IWTSVirtualChannelCallback)
COM_INTERFACE_ENTRY(IWTSListenerCallback)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
// IWTSPlugin.
//
HRESULT STDMETHODCALLTYPE
Initialize(IWTSVirtualChannelManager *pChannelMgr);
HRESULT STDMETHODCALLTYPE Connected();
HRESULT STDMETHODCALLTYPE Disconnected(DWORD dwDisconnectCode)
{
// Prevent C4100 "unreferenced parameter" warnings.
dwDisconnectCode;
return S_OK;
}
HRESULT STDMETHODCALLTYPE Terminated()
{
return S_OK;
}
VOID SetChannel(IWTSVirtualChannel *pChannel, struct threadargs *pTa);
// IWTSVirtualChannelCallbackdwDummyThreadId
//
HRESULT STDMETHODCALLTYPE OnDataReceived(ULONG cbSize, __in_bcount(cbSize) BYTE *pBuffer);
HRESULT STDMETHODCALLTYPE OnClose()
{
ta.run = FALSE;
//DebugPrint(0, L"[*] Terminating thread, closing socket and channel0");
TerminateThreads();
closesocket(gpta->sockserver);
ta.m_ptrChannel = NULL;
WSACleanup();
return S_OK;
}
HRESULT STDMETHODCALLTYPE
OnNewChannelConnection(
__in IWTSVirtualChannel *pChannel,
__in_opt BSTR data,
__out BOOL *pbAccept,
__out IWTSVirtualChannelCallback **ppCallback);
// non-inherited ones
struct threadargs *gpta;
struct arguments running_args;
static struct threads *SocksOverRDPPlugin::AddThread(DWORD dwThreadId, SOCKET s);
static VOID SocksOverRDPPlugin::DeleteThread(DWORD dwThreadId);
static VOID SocksOverRDPPlugin::TerminateThreads();
static struct threads *SocksOverRDPPlugin::LookupThread(DWORD dwThreadId);
static VOID SocksOverRDPPlugin::StopThread(DWORD dwThreadId);
static VOID SocksOverRDPPlugin::DebugPrint(HRESULT hrDbg, __in_z LPWSTR fmt, ...);
LONG SocksOverRDPPlugin::GetDWORDRegKey(HKEY hKey, WCHAR *strValueName, DWORD *nValue);
LONG SocksOverRDPPlugin::GetStringRegKey(HKEY hKey, WCHAR *strValueName, WCHAR **strValue);
BOOL SocksOverRDPPlugin::GetRegistrySettings();
static DWORD WINAPI SocksOverRDPPlugin::RelayToRDPChannel(PVOID param);
static DWORD WINAPI SocksOverRDPPlugin::ListenerThread(PVOID param);
};
OBJECT_ENTRY_AUTO(__uuidof(CompReg), SocksOverRDPPlugin)
// Add thread to linked list
struct threads *SocksOverRDPPlugin::AddThread(DWORD dwThreadId, SOCKET s)
{
struct threads *rolling;
struct threads *ThreadStruct;
DWORD dwWaitResult = WaitForSingleObject(ghLLMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
ThreadStruct = (struct threads *)malloc(sizeof(struct threads));
ThreadStruct->dwThreadId = dwThreadId;
ThreadStruct->hThread = GetCurrentThread();
ThreadStruct->run = TRUE;
ThreadStruct->s = s;
ThreadStruct->next = NULL;
if (ThreadHead == NULL)
{
ThreadHead = ThreadStruct;
}
else
{
rolling = ThreadHead;
while (rolling->next)
{
rolling = rolling->next;
}
rolling->next = ThreadStruct;
}
if (!ReleaseMutex(ghLLMutex))
{
if (bVerbose) DebugPrint(0, L"[*] AddThread Release failed: %08X", dwThreadId);
}
return ThreadStruct;
break;
case WAIT_ABANDONED:
if (bVerbose) DebugPrint(0, L"[*] AddThread abandoned: %08X", GetCurrentThreadId());
return NULL;
}
return NULL;
}
// Remove thread from linked list
VOID SocksOverRDPPlugin::DeleteThread(DWORD dwThreadId)
{
struct threads *rolling;
struct threads *prev = NULL;
DWORD dwWaitResult = WaitForSingleObject(ghLLMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
if (!ThreadHead)
{
if (!ReleaseMutex(ghLLMutex))
{
if (bVerbose) DebugPrint(0, L"[*] DeleteThread Release failed: %08X", GetCurrentThreadId());
}
return;
}
rolling = ThreadHead;
while (rolling->dwThreadId != dwThreadId)
{
prev = rolling;
rolling = rolling->next;
}
if (prev)
{
if (rolling->next)
{
prev->next = rolling->next;
}
else
{
prev->next = NULL;
}
}
else
{
if (ThreadHead->next)
{
ThreadHead = ThreadHead->next;
}
else
{
ThreadHead = NULL;
}
}
rolling->run = FALSE;
closesocket(rolling->s);
rolling->dwThreadId = 0xffffffff;
rolling->next = FALSE;
rolling->hThread = NULL;
rolling->s = NULL;
free(rolling);
rolling = NULL;
if (!ReleaseMutex(ghLLMutex))
{
if (bVerbose) DebugPrint(0, L"[*] DeleteThread Release failed: %08X", GetCurrentThreadId());
}
return;
break;
case WAIT_ABANDONED:
if (bVerbose) DebugPrint(0, L"[*] DeleteThread abandoned: %08X", GetCurrentThreadId());
return;
}
}
/*
Terminate all running threads that handle communication
by setting the loop condition to FALSE and closing socket.
*/
VOID SocksOverRDPPlugin::TerminateThreads()
{
struct threads *rolling;
DWORD dwWaitResult = WaitForSingleObject(ghLLMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
rolling = ThreadHead;
if (rolling == NULL)
{
if (bVerbose) DebugPrint(0, L"[*] Nothing to terminate. Threadhead empty. %08X", GetCurrentThreadId());
}
while (rolling)
{
rolling->run = FALSE;
closesocket(rolling->s);
rolling = rolling->next;
}
if (!ReleaseMutex(ghLLMutex))
{
if (bVerbose) DebugPrint(0, L"[*] TerminateThreads Release failed: %08X", GetCurrentThreadId());
}
return;
break;
case WAIT_ABANDONED:
if (bVerbose) DebugPrint(0, L"[*] TerminateThreads abandoned: %08X", GetCurrentThreadId());
return;
}
}
// Stopping a specific thread gently by setting the loop condition to FALSE
VOID SocksOverRDPPlugin::StopThread(DWORD dwThreadId)
{
struct threads *rolling;
DWORD dwWaitResult = WaitForSingleObject(ghLLMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
rolling = ThreadHead;
while (rolling)
{
if (rolling->dwThreadId == dwThreadId)
{
rolling->run = FALSE;
if (!ReleaseMutex(ghLLMutex))
{
if (bVerbose) DebugPrint(0, L"[*] StopThread Release failed0: %08X", GetCurrentThreadId());
}
return;
}
rolling = rolling->next;
}
if (!ReleaseMutex(ghLLMutex))
{
if (bVerbose) DebugPrint(0, L"[*] StopThread Release failed1: %08X", GetCurrentThreadId());
}
return;
break;
case WAIT_ABANDONED:
if (bVerbose) DebugPrint(0, L"[*] lookupThread abandoned: %08X", GetCurrentThreadId());
return;
}
return;
}
// Look up thread and return a pointer to it by ThreadId
struct threads *SocksOverRDPPlugin::LookupThread(DWORD dwThreadId)
{
struct threads *rolling;
DWORD dwWaitResult = WaitForSingleObject(ghLLMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
rolling = ThreadHead;
while (rolling)
{
if (rolling->dwThreadId == dwThreadId)
{
if (!ReleaseMutex(ghLLMutex))
{
if (bVerbose) DebugPrint(0, L"[*] lookupThread Release failed0: %08X", GetCurrentThreadId());
}
return rolling;
}
rolling = rolling->next;
}
if (!ReleaseMutex(ghLLMutex))
{
if (bVerbose) DebugPrint(0, L"[*] lookupThread Release failed1: %08X", GetCurrentThreadId());
}
return NULL;
break;
case WAIT_ABANDONED:
if (bVerbose) DebugPrint(0, L"[*] lookupThread abandoned: %08X", GetCurrentThreadId());
return NULL;
}
return NULL;
}
// Debug/Verbose Print function, message shows up in the debugger.
VOID SocksOverRDPPlugin::DebugPrint(HRESULT hrDbg, __in_z LPWSTR fmt, ...)
{
HRESULT hr;
TCHAR Buffer[DEBUG_PRINT_BUFFER_SIZE];
size_t Len;
hr = StringCchPrintf(Buffer, DEBUG_PRINT_BUFFER_SIZE, TEXT("[hr=0x%8x]"), hrDbg);
assert(SUCCEEDED(hr)); // buffer is sure to be big enough
hr = StringCchLength(Buffer, DEBUG_PRINT_BUFFER_SIZE, &Len);
assert(SUCCEEDED(hr)); // StringCchPrintf is supposed to always NULL term
va_list argptr;
va_start(argptr, fmt);
hr = StringCchVPrintf(Buffer + Len, DEBUG_PRINT_BUFFER_SIZE - Len,
fmt, argptr);
// the above could fail but we don't care since we
// should get a NULL terminated partial string
// insert terminating eol (despite failure)
hr = StringCchLength(Buffer, DEBUG_PRINT_BUFFER_SIZE, &Len);
assert(SUCCEEDED(hr)); // again there should be a NULL term
if (Len < DEBUG_PRINT_BUFFER_SIZE - 1)
{
Len++;
Buffer[Len] = TEXT('\0');
}
Buffer[Len - 1] = TEXT('\n');
OutputDebugString(Buffer);
}
LONG SocksOverRDPPlugin::GetDWORDRegKey(HKEY hKey, WCHAR *strValueName, DWORD *nValue)
{
DWORD dwBufferSize(sizeof(DWORD));
DWORD nResult;
LONG nError;
if ((nError = RegQueryValueEx(hKey, strValueName, 0, NULL, (LPBYTE)&nResult, &dwBufferSize)) == ERROR_SUCCESS)
{
*nValue = nResult;
}
return nError;
}
LONG SocksOverRDPPlugin::GetStringRegKey(HKEY hKey, WCHAR *strValueName, WCHAR **strValue)
{
LPVOID szTemp = NULL;
DWORD buflen = 255;
LONG nError;
if ((szTemp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (size_t)buflen)) == NULL)
{
if (bVerbose) DebugPrint(GetLastError(), L"[-] Error allocating heap for read buffer %ld", GetLastError());
return -1;
}
if ((nError = RegQueryValueExW(hKey, strValueName, 0, NULL, (LPBYTE)szTemp, &buflen)) != ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, szTemp);
szTemp = NULL;
}
*strValue = (WCHAR *)szTemp;
return nError;
}
BOOL SocksOverRDPPlugin::GetRegistrySettings()
{
HKEY hKey;
LONG lRes;
WCHAR *szTemp;
if ((lRes = RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Terminal Server Client\\Default\\AddIns\\SocksOverRDP-Plugin\\", 0, KEY_READ, &hKey)) != ERROR_SUCCESS)
{
DebugPrint(lRes, L"[-] Error opening registry hive/key");
return FALSE;
}
GetDWORDRegKey(hKey, L"enabled", &running_args.enabled);
GetStringRegKey(hKey, L"ip", &szTemp);
if (szTemp != NULL)
{
if (wcslen(szTemp) < 16)
{
running_args.ip = szTemp;
}
else
{
MessageBox(NULL, L"IP too long. Please fix it under the following key:\r\nHKCU\\SOFTWARE\\Microsoft\\Terminal Server Client\\Default\\AddIns\\SocksOverRDP-Plugin\\", L"Registry value error", MB_OK);
}
}
GetStringRegKey(hKey, L"port", &szTemp);
if (szTemp != NULL)
{
if (wcslen(szTemp) < 6)
{
running_args.port = szTemp;
}
else
{
MessageBox(NULL, L"Port too long. Please fix it under the following key:\r\nHKCU\\SOFTWARE\\Microsoft\\Terminal Server Client\\Default\\AddIns\\SocksOverRDP-Plugin\\", L"Registry value error", MB_OK);
}
}
return TRUE;
}
// IWTSPlugin::Initialize implementation.
HRESULT SocksOverRDPPlugin::Initialize(__in IWTSVirtualChannelManager *pChannelMgr)
{
HRESULT hr;
CComObject<SocksOverRDPPlugin> *pListenerCallback;
CComPtr<SocksOverRDPPlugin> ptrListenerCallback;
CComPtr<IWTSListener> ptrListener;
WCHAR enabledmsg[256];
running_args.enabled = 0;
running_args.port = L"1080";
running_args.ip = L"127.0.0.1";
if (!GetRegistrySettings())
{
DebugPrint(-1, L"[-] Could not access the registry settings");
}
if (!running_args.enabled)
{
DebugPrint(0, L"[*] Plugin disabled");
return -1;
}
wnsprintf(enabledmsg, 255, L"The SocksOverRDP plugin is enabled. When the server binary gets executed, it will listen on: %s:%s", running_args.ip, running_args.port);
MessageBox(NULL, enabledmsg, L"SocksOverRDP plugin is enabled", MB_OK | MB_ICONWARNING);
// Create an instance of the CSampleListenerCallback object.
hr = CComObject<SocksOverRDPPlugin>::CreateInstance(&pListenerCallback);
CHECK_QUIT_HR("SocksOverRDPPlugin::CreateInstance");
ptrListenerCallback = pListenerCallback;
// Attach the callback to the endpoint.
hr = pChannelMgr->CreateListener(
SocksOverRDP_CHANNEL_NAME,
0,
(SocksOverRDPPlugin*)ptrListenerCallback,
&ptrListener);
CHECK_QUIT_HR("CreateListener");
return hr;
}
// MSTSC connected to server over RDP
HRESULT STDMETHODCALLTYPE SocksOverRDPPlugin::Connected()
{
return S_OK;
}
/*
This thread is started for each and every connection that is made to the socks
proxy. This part only handles the Client->RDP communication.
Whatever comes from the client will be piped into the RDP channel with prefixed
with: DWORD(threadid)+DWORD(sizeof(following_data))+BYTE(closurebit)
*/
DWORD SocksOverRDPPlugin::RelayToRDPChannel(PVOID param)
{
SOCKET c = (SOCKET)param;
DWORD dwWaitResult, dwThreadId = GetCurrentThreadId();
char buf[BUF_SIZE + sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE)];
int ret;
struct threads *pta;
pta = AddThread(dwThreadId, c);
if (!pta)
{
if (bVerbose) DebugPrint(0, L"%08X: Adding thread failure.", dwThreadId);
return -1;
}
// running till error or thread stopped
while (pta->run)
{
// reading from client socket
if ((ret = recv(c, buf + sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE), BUF_SIZE, 0)) > 0)
{
// might have been blocked for a long time and the thread should be
// stopped already
if (!pta->run) break;
// prefixing with the necessities
memcpy(buf, &dwThreadId, sizeof(DWORD));
memcpy(buf + sizeof(DWORD), &ret, sizeof(DWORD));
buf[sizeof(DWORD) + sizeof(DWORD)] = 0;
}
else
{
// SOCKET_ERROR or RST was received
if (!pta->run)
break;
if (ret && bVerbose)
DebugPrint(0, L"%08X: SOCKS thread(%d) Rsend() failed with errorelayToRDPChannel recv error: %ld %ld", dwThreadId, dwThreadId, ret, WSAGetLastError());
ret = 0;
memcpy(buf, &dwThreadId, sizeof(DWORD));
memcpy(buf + sizeof(DWORD), &ret, sizeof(DWORD));
buf[sizeof(DWORD) + sizeof(DWORD)] = 1;
pta->run = FALSE;
}
// wait on mutex, when it is acquired, block other threads to write
dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
// write prefixed received data on channel
if (ta.m_ptrChannel != NULL)
if (ta.m_ptrChannel->Write(ret + sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE), (BYTE *)buf, NULL))
{
if (bVerbose) DebugPrint(0, L"Write to channel failed for some reason.");
}
if (!ReleaseMutex(ghMutex))
{
if (bVerbose) DebugPrint(0, L"Release failed");
}
break;
case WAIT_ABANDONED:
return FALSE;
}
}
DeleteThread(dwThreadId);
return 0;
}
DWORD SocksOverRDPPlugin::ListenerThread(PVOID param)
{
WSADATA wsaData;
ADDRINFOW *result = NULL;
ADDRINFOW hints;
SOCKET s, c;
HANDLE hDummyThread;
DWORD dwDummyThreadId;
int ret;
DebugPrint(0, L"[*] Setting up server socket");
if ((ret = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
{
DebugPrint(ret, L"WSAStartup() failed with error: %ld", ret);
return -1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
if ((ret = GetAddrInfoW(ta.running_args->ip, ta.running_args->port, &hints, &result)) != 0) {
DebugPrint(ret, L"[-] GetAddrInfoW() failed with error: %ld", ret);
return -1;
}
if ((s = socket(result->ai_family, result->ai_socktype, result->ai_protocol)) == INVALID_SOCKET) {
DebugPrint(WSAGetLastError(), L"[-] socket() failed with error: %ld", WSAGetLastError());
FreeAddrInfoW(result);
return -1;
}
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, "1", 1) == SOCKET_ERROR)
{
DebugPrint(WSAGetLastError(), L"[-] setsockopt() failed with error: %ld", WSAGetLastError());
}
ta.sockserver = s;
if ((ret = bind(s, result->ai_addr, (int)result->ai_addrlen)) == SOCKET_ERROR) {
DebugPrint(WSAGetLastError(), L"[-] bind() failed with error: %ld", WSAGetLastError());
FreeAddrInfoW(result);
closesocket(s);
return -1;
}
FreeAddrInfoW(result);
DebugPrint(0, L"[*] Listening on: %s:%s", ta.running_args->ip, ta.running_args->port);
if ((ret = listen(s, SOMAXCONN)) == SOCKET_ERROR) {
DebugPrint(0, L"[-] listen() failed with error: %ld", WSAGetLastError());
closesocket(s);
return -1;
}
// while till the RDP connection wasn't closed and
// create a new thread for all new connections
while (ta.run)
{
if ((c = accept(s, NULL, NULL)) == INVALID_SOCKET) {
DebugPrint(0, L"[-] accept() failed with error: %ld", WSAGetLastError());
return -1;
}
hDummyThread = CreateThread(
NULL,
0,
&SocksOverRDPPlugin::RelayToRDPChannel,
(void *)c,
0,
&dwDummyThreadId);
if (bVerbose) DebugPrint(0, L"[+] New thread created: %08X", dwDummyThreadId);
}
return 0;
}
// IWTSListenerCallback::OnNewChannelConnection implementation.
HRESULT SocksOverRDPPlugin::OnNewChannelConnection(__in IWTSVirtualChannel *pChannel,
__in_opt BSTR data, __out BOOL *pbAccept, __out IWTSVirtualChannelCallback **ppCallback)
{
HRESULT hr;
CComObject<SocksOverRDPPlugin> *pCallback;
CComPtr<SocksOverRDPPlugin> ptrCallback;
// Prevent C4100 "unreferenced parameter" warnings.
data;
*pbAccept = FALSE;
hr = CComObject<SocksOverRDPPlugin>::CreateInstance(&pCallback);
CHECK_QUIT_HR("SocksOverRDPPlugin::CreateInstance");
ptrCallback = pCallback;
ptrCallback->SetChannel(pChannel, &ta);
ta.running_args = &running_args;
ta.m_ptrChannel = pChannel;
ta.run = TRUE;
ghMutex = CreateMutex(NULL, FALSE, NULL);
ghLLMutex = CreateMutex(NULL, FALSE, NULL);
running_args.enabled = 0;
running_args.port = L"1080";
running_args.ip = L"127.0.0.1";
if (!GetRegistrySettings())
{
DebugPrint(-1, L"[-] Could not access the registry settings");
}
DebugPrint(0, L"[+] Starting Listener thread");
// Create main thread that will spawn other threads upon new connections
HANDLE hListenerThread = CreateThread(
NULL,
0,
&SocksOverRDPPlugin::ListenerThread,
NULL,
0,
NULL);
ta.hThread = hListenerThread;
*ppCallback = ptrCallback;
(*ppCallback)->AddRef();
*pbAccept = TRUE;
return hr;
}
VOID SocksOverRDPPlugin::SetChannel(IWTSVirtualChannel *pChannel, struct threadargs *pTa)
{
m_ptrChannel = pChannel;
gpta = pTa;
}
// When data is received from the RDP server on the channel, this function is
// getting called with the *data on stack
HRESULT STDMETHODCALLTYPE SocksOverRDPPlugin::OnDataReceived(ULONG cbSize, __in_bcount(cbSize) BYTE *pBuffer)
{
DWORD dwThreadId, ret, dwRecvdLen, cbFullSize;
BOOL bClose = FALSE, ofused = FALSE;
char *buf;
struct threads *pta;
buf = (char*)pBuffer;
cbFullSize = cbSize;
// if overflow was present from previous call, it was saved and should be
// prepended with the new data
// ofused if set, signals that szOverflow has the data instead of pBuffer
if (dwOverflow)
{
if (bVerbose) DebugPrint(0, L"Overflow was present from previous call. Stored bytes: %ld. Received bytes: %ld", dwOverflow, cbSize);
memcpy_s(szOverflow + dwOverflow, BUF_SIZE*4, pBuffer, cbSize);
buf = szOverflow;
cbFullSize = cbSize + dwOverflow;
dwOverflow = 0;
ofused = TRUE;
}
while (cbFullSize)
{
// parsing the header, getting threadId from server side, that matches
// the local threadID; recvlen which has the appended data length ;
// bClose bit which shows weather the connection will be/was closed
// on the server side.
memcpy(&dwThreadId, buf, sizeof(DWORD));
memcpy(&dwRecvdLen, buf + sizeof(DWORD), sizeof(DWORD));
if (buf[sizeof(DWORD) + sizeof(DWORD)] == 0x01) bClose = TRUE;
// finding thread based on the header. If no thread found, that is a
// problem, since there is no thread that has the associated info for
// this received data
pta = LookupThread(dwThreadId);
if (pta == NULL)
return -1;
if (bVerbose) DebugPrint(0, L"%08X: Read: %ld content length: %ld", dwThreadId, cbFullSize, dwRecvdLen);
if (dwRecvdLen <= cbFullSize - (sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE)))
{
if (bVerbose) DebugPrint(0, L"%08X: Last read, smaller or equal.", dwThreadId);
if (dwRecvdLen)
{
if (pta->s)
{
// send recvl bytes from the received data to the
// corresponding socket
if ((ret = send(pta->s, buf + sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE), dwRecvdLen, 0)) == SOCKET_ERROR)
{
// error happened, stopping thread gently and
// recalculating pointers to the next packet
StopThread(dwThreadId);
if (bVerbose) DebugPrint(0, L"%08X: send() failed with error %ld %ld", dwThreadId, ret, WSAGetLastError());
cbFullSize -= (dwRecvdLen + sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE));
buf += (dwRecvdLen + sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE));
}
else
{
// recalculating pointers to the next packet
cbFullSize -= (ret + sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE));
buf += (ret + sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE));
if (bVerbose) DebugPrint(0, L"%08X: Sent on socket: %ld. cbFullSize: %ld", dwThreadId, ret, cbFullSize);
}
}
}
// bClose bit was set on the server side. Closing down connection
if (bClose)
{
StopThread(dwThreadId);
if (pta->s)
shutdown(pta->s, SD_SEND);
// only RST was sent from server side
if (!dwRecvdLen)
{
cbFullSize -= sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE);
buf += sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE);
}
}
}
else
{
// data remained on the buffer, less than specified in the header
if (bVerbose) DebugPrint(0, L"!!! OVERFLOW HAPPENED %ld > %ld", dwRecvdLen, cbFullSize);
if (ofused)
{
// ofused set, memmove needed
memmove_s(szOverflow, BUF_SIZE * 4, buf, cbFullSize);
dwOverflow = cbFullSize;
}
else
{
memcpy_s(szOverflow, BUF_SIZE * 4, buf, cbFullSize);
dwOverflow = cbFullSize;
}
// not enough data to send, need to get more, stopping loop
cbFullSize = 0;
}
}
return S_OK;
}
@@ -0,0 +1,10 @@
; SocksOverRDP-Plugin.def : Declares the module parameters.
LIBRARY
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
DllInstall PRIVATE
+144
View File
@@ -0,0 +1,144 @@
// TsClientPlgn.h : Declaration of the CTsClientPlgn
#pragma once
#include "stdafx.h"
#include "resource.h" // main symbols
#include "SocksOverRDPPlugin_i.h"
// debug
#include <StrSafe.h>
#include <assert.h>
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif
// CTsClientPlgn
class ATL_NO_VTABLE CTsClientPlgn :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CTsClientPlgn, &CLSID_CompReg>,
public IDispatchImpl<IComponentRegistrar, &IID_IComponentRegistrar, &LIBID_SocksOverRDPPluginLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IWTSPlugin,
public IWTSListenerCallback,
public IWTSVirtualChannelCallback
{
public:
CTsClientPlgn(): _hCurrentFile(INVALID_HANDLE_VALUE)
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_SocksOverRDPCLIENTPLUGIN)
BEGIN_COM_MAP(CTsClientPlgn)
COM_INTERFACE_ENTRY(IComponentRegistrar)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IWTSPlugin)
COM_INTERFACE_ENTRY(IWTSListenerCallback)
COM_INTERFACE_ENTRY(IWTSVirtualChannelCallback)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
// IWTSPlugin
public:
/*
* Called immediately after instantiating the COM class
*/
STDMETHOD(Initialize)(
IWTSVirtualChannelManager *pChannelMgr
);
/*
* Called when the TS client is connected to the TS server
*/
STDMETHOD(Connected)();
/*
* Called when the TS client is disconnected to the TS server
* Might be followed by another Connected() call
*/
STDMETHOD(Disconnected)(
DWORD dwDisconnectCode
);
/*
* The last method called by the TS client before
* terminating the object
*/
STDMETHOD(Terminated)();
// IWTSListenerCallback
public:
VOID CTsClientPlgn::SetChannel(IWTSVirtualChannel *pChannel);
public:
/*
* Called whenever a request for new channel connection
* from the server is received.
*/
STDMETHOD(OnNewChannelConnection)(
IWTSVirtualChannel *pChannel,
BSTR data, // optional data passed as part of the connect method
BOOL *pbAccept, // the callee should return TRUE if connection is accepted
IWTSVirtualChannelCallback **ppCallback // connection related events
);
// IWTSVirtualChannelCallback
public:
/*
* Called whenever a full message from the server is received
* The message is fully reassembled and has the exact size
* as the Write() call on the server
*/
STDMETHOD(OnDataReceived)(
ULONG cbSize, // size of data in bytes
BYTE *pBuffer // data buffer
);
/*
* The channel is disconnected, all Write() calls will fail
* no more incomming data is expected.
*/
STDMETHOD(OnClose)();
private:
HRESULT CleanState();
HRESULT StartFile(
__in_z LPWSTR szFileName,
BOOL bDir);
HRESULT WriteData(
__in_bcount(usLen) PBYTE pData,
USHORT usLen);
HRESULT EndFile(BOOL bDir);
CComPtr<IWTSListener> _spListener;
CComPtr<IWTSVirtualChannel> _spChannel;
HANDLE _hCurrentFile;
WStringVector _vDirList;
};
//OBJECT_ENTRY_AUTO(__uuidof(CompReg), CTsClientPlgn)
// DEBUG:
#define DEBUG_PRINT_BUFFER_SIZE 1024
Binary file not shown.
@@ -0,0 +1,52 @@
HKCR
{
CLSID
{
SocksOverRDP-Plugin.SocksOverRDP-Plugin.1 = s 'SocksOverRDP-Plugin Class'
{
CLSID = s '{61715a27-63a8-4dc1-9857-83eb00fb60a3}'
}
SocksOverRDP-Plugin.SocksOverRDP-Plugin = s 'SocksOverRDP-Plugin Class'
{
CLSID = s '{61715a27-63a8-4dc1-9857-83eb00fb60a3}'
CurVer = s 'SocksOverRDP-Plugin.SocksOverRDP-Plugin.1'
}
ForceRemove {61715a27-63a8-4dc1-9857-83eb00fb60a3} = s 'SocksOverRDP-Plugin Class'
{
ProgID = s 'SocksOverRDP-Plugin.SocksOverRDP-Plugin.1'
VersionIndependentProgID = s 'SocksOverRDP-Plugin.SocksOverRDP-Plugin'
ForceRemove 'Programmable'
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Free'
}
'TypeLib' = s '{392B9DEE-7E00-4C58-831B-50C58EAA887F}'
}
}
}
HKCU
{
Software
{
Microsoft
{
'Terminal Server Client'
{
Default
{
AddIns
{
SocksOverRDP-Plugin
{
val Name = s '{61715a27-63a8-4dc1-9857-83eb00fb60a3}'
val enabled = d '1'
val ip = s '127.0.0.1'
val port = s '1080'
}
}
}
}
}
}
}
@@ -0,0 +1,285 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9402DF45-A060-4881-9F64-D16E094B97A7}</ProjectGuid>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<Keyword>AtlProj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IgnoreImportLibrary>true</IgnoreImportLibrary>
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IgnoreImportLibrary>true</IgnoreImportLibrary>
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IgnoreImportLibrary>true</IgnoreImportLibrary>
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IgnoreImportLibrary>true</IgnoreImportLibrary>
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<TargetEnvironment>Win32</TargetEnvironment>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>SocksOverRDPPlugin_i.h</HeaderFileName>
<InterfaceIdentifierFileName>SocksOverRDPPlugin_i.c</InterfaceIdentifierFileName>
<ProxyFileName>SocksOverRDPPlugin_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)SocksOverRDPPlugin.tlb</TypeLibraryName>
<DllDataFileName />
<ValidateAllParameters>true</ValidateAllParameters>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>.\SocksOverRDP-Plugin.def</ModuleDefinitionFile>
<AdditionalDependencies>comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<RegisterOutput>true</RegisterOutput>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>SocksOverRDPPlugin_i.h</HeaderFileName>
<InterfaceIdentifierFileName>SocksOverRDPPlugin_i.c</InterfaceIdentifierFileName>
<ProxyFileName>SocksOverRDPPlugin_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)SocksOverRDPPlugin.tlb</TypeLibraryName>
<DllDataFileName />
<ValidateAllParameters>true</ValidateAllParameters>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>.\SocksOverRDP-Plugin.def</ModuleDefinitionFile>
<AdditionalDependencies>comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<RegisterOutput>true</RegisterOutput>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<TargetEnvironment>Win32</TargetEnvironment>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>SocksOverRDPPlugin_i.h</HeaderFileName>
<InterfaceIdentifierFileName>SocksOverRDPPlugin_i.c</InterfaceIdentifierFileName>
<ProxyFileName>SocksOverRDPPlugin_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)SocksOverRDPPlugin.tlb</TypeLibraryName>
<DllDataFileName />
<ValidateAllParameters>true</ValidateAllParameters>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>.\SocksOverRDP-Plugin.def</ModuleDefinitionFile>
<AdditionalDependencies>comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<RegisterOutput>true</RegisterOutput>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>_WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>SocksOverRDPPlugin_i.h</HeaderFileName>
<InterfaceIdentifierFileName>SocksOverRDPPlugin_i.c</InterfaceIdentifierFileName>
<ProxyFileName>SocksOverRDPPlugin_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)SocksOverRDPPlugin.tlb</TypeLibraryName>
<DllDataFileName />
<ValidateAllParameters>true</ValidateAllParameters>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>.\SocksOverRDP-Plugin.def</ModuleDefinitionFile>
<AdditionalDependencies>comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<RegisterOutput>true</RegisterOutput>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="compreg.cpp" />
<ClCompile Include="SocksOverRDP-Plugin.cpp" />
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="dllfunc.cpp" />
<ClCompile Include="SocksOverRDPPlugin_i.c">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="compreg.h" />
<ClInclude Include="dllmain.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="SocksOverRDP-Plugin.h" />
<ClInclude Include="SocksOverRDPPlugin_i.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="SocksOverRDP-Plugin.rc" />
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<None Include="SocksOverRDP-Plugin.def" />
<None Include="SocksOverRDP-Plugin.rgs" />
</ItemGroup>
<ItemGroup>
<Midl Include="SocksOverRDPPlugin.idl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Generated Files">
<UniqueIdentifier>{2467f173-a17f-4363-a3f3-5f66776727f8}</UniqueIdentifier>
<SourceControlFiles>False</SourceControlFiles>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="compreg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SocksOverRDPPlugin_i.c">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="dllfunc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SocksOverRDP-Plugin.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dllmain.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="compreg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SocksOverRDPPlugin_i.h">
<Filter>Generated Files</Filter>
</ClInclude>
<ClInclude Include="SocksOverRDP-Plugin.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="SocksOverRDP-Plugin.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<None Include="SocksOverRDP-Plugin.rgs">
<Filter>Resource Files</Filter>
</None>
<None Include="SocksOverRDP-Plugin.def">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Midl Include="SocksOverRDPPlugin.idl">
<Filter>Source Files</Filter>
</Midl>
</ItemGroup>
</Project>
@@ -0,0 +1,174 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{15DEE2D8-6972-49C0-9369-35730A29A2CF}</ProjectGuid>
<Keyword>AtlPSProj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IntDir>$(Platform)\$(Configuration)PS\</IntDir>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IntDir>$(Platform)\$(Configuration)PS\</IntDir>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IntDir>$(Platform)\$(Configuration)PS\</IntDir>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IntDir>$(Platform)\$(Configuration)PS\</IntDir>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;REGISTER_PROXY_DLL;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;ole32.lib;advapi32.lib;comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>SocksOverRDP-PluginPS.def</ModuleDefinitionFile>
<RegisterOutput>true</RegisterOutput>
</Link>
<PreBuildEvent>
<Command>if exist dlldata.c goto :END
echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project.
Exit 1
:END
</Command>
<Message>Checking for required files</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>REGISTER_PROXY_DLL;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;ole32.lib;advapi32.lib;comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>SocksOverRDP-PluginPS.def</ModuleDefinitionFile>
<RegisterOutput>true</RegisterOutput>
</Link>
<PreBuildEvent>
<Command>if exist dlldata.c goto :END
echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project.
Exit 1
:END
</Command>
<Message>Checking for required files</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;REGISTER_PROXY_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;ole32.lib;advapi32.lib;comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>SocksOverRDP-PluginPS.def</ModuleDefinitionFile>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<RegisterOutput>true</RegisterOutput>
</Link>
<PreBuildEvent>
<Command>if exist dlldata.c goto :END
echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project.
Exit 1
:END
</Command>
<Message>Checking for required files</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>REGISTER_PROXY_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;ole32.lib;advapi32.lib;comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>SocksOverRDP-PluginPS.def</ModuleDefinitionFile>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<RegisterOutput>true</RegisterOutput>
</Link>
<PreBuildEvent>
<Command>if exist dlldata.c goto :END
echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project.
Exit 1
:END
</Command>
<Message>Checking for required files</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="SocksOverRDP-Pluginps.def" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dlldata.c" />
<ClCompile Include="SocksOverRDPPlugin_i.c" />
<ClCompile Include="SocksOverRDPPlugin_p.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{3ae88138-7c28-4919-a9b2-4b5e1473c72b}</UniqueIdentifier>
</Filter>
<Filter Include="Generated Files">
<UniqueIdentifier>{d3ce00e0-04ef-4a7b-ad63-435441b697a5}</UniqueIdentifier>
<SourceControlFiles>False</SourceControlFiles>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="SocksOverRDP-Pluginps.def" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="SocksOverRDPPlugin_i.c">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="SocksOverRDPPlugin_p.c">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="dlldata.c">
<Filter>Generated Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
@@ -0,0 +1,8 @@
LIBRARY
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
@@ -0,0 +1,42 @@
// SocksOverRDPPlugin.idl : IDL source for SocksOverRDP-Plugin
//
// This file will be processed by the MIDL tool to
// produce the type library (SocksOverRDPPlugin.tlb) and marshalling code.
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(a817e7a2-43fa-11d0-9e44-00aa00b6770a),
dual,
pointer_default(unique)
]
interface IComponentRegistrar : IDispatch
{
[id(1)] HRESULT Attach([in] BSTR bstrPath);
[id(2)] HRESULT RegisterAll();
[id(3)] HRESULT UnregisterAll();
[id(4)] HRESULT GetComponents([out] SAFEARRAY(BSTR)* pbstrCLSIDs, [out] SAFEARRAY(BSTR)* pbstrDescriptions);
[id(5)] HRESULT RegisterComponent([in] BSTR bstrCLSID);
[id(6)] HRESULT UnregisterComponent([in] BSTR bstrCLSID);
};
[
uuid(392B9DEE-7E00-4C58-831B-50C58EAA887F),
version(1.0),
custom(a817e7a1-43fa-11d0-9e44-00aa00b6770a,"{61715a27-63a8-4dc1-9857-83eb00fb60a3}")
]
library SocksOverRDPPluginLib
{
importlib("stdole2.tlb");
[
uuid(61715a27-63a8-4dc1-9857-83eb00fb60a3)
]
coclass CompReg
{
[default] interface IComponentRegistrar;
};
};
+7
View File
@@ -0,0 +1,7 @@
// compreg.cpp : Implementation of CCompReg
#include "stdafx.h"
#include "compreg.h"
// CCompReg
+7
View File
@@ -0,0 +1,7 @@
// compreg.h : Declaration of the CCompReg
#pragma once
#include "resource.h" // main symbols
#include "SocksOverRDPPlugin_i.h"
+92
View File
@@ -0,0 +1,92 @@
/*
* MIT License
*
* Copyright(c) 2020 Balazs SocksOverRDP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "stdafx.h"
#include "resource.h"
#include "SocksOverRDPPlugin_i.h"
#include "dllmain.h"
#include "compreg.h"
using namespace ATL;
// Used to determine whether the DLL can be unloaded by OLE.
STDAPI DllCanUnloadNow(void)
{
return _AtlModule.DllCanUnloadNow();
}
// Returns a class factory to create an object of the requested type.
_Check_return_
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID* ppv)
{
return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
}
// DllRegisterServer - Adds entries to the system registry.
STDAPI DllRegisterServer(void)
{
// registers object, typelib and all interfaces in typelib
HRESULT hr = _AtlModule.DllRegisterServer();
return hr;
}
// DllUnregisterServer - Removes entries from the system registry.
STDAPI DllUnregisterServer(void)
{
HRESULT hr = _AtlModule.DllUnregisterServer();
return hr;
}
// DllInstall - Adds/Removes entries to the system registry per user per machine.
STDAPI DllInstall(BOOL bInstall, _In_opt_ LPCWSTR pszCmdLine)
{
HRESULT hr = E_FAIL;
static const wchar_t szUserSwitch[] = L"user";
if (pszCmdLine != NULL)
{
if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0)
{
ATL::AtlSetPerUserRegistration(true);
}
}
if (bInstall)
{
hr = DllRegisterServer();
if (FAILED(hr))
{
DllUnregisterServer();
}
}
else
{
hr = DllUnregisterServer();
}
return hr;
}
+38
View File
@@ -0,0 +1,38 @@
/*
* MIT License
*
* Copyright(c) 2020 Balazs Bucsay
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "stdafx.h"
#include "resource.h"
#include "SocksOverRDPPlugin_i.h"
#include "dllmain.h"
#include "compreg.h"
CSocksOverRDPPluginModule _AtlModule;
// DLL Entry Point
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
hInstance;
return _AtlModule.DllMain(dwReason, lpReserved);
}
+10
View File
@@ -0,0 +1,10 @@
// dllmain.h : Declaration of module class.
class CSocksOverRDPPluginModule : public ATL::CAtlDllModuleT< CSocksOverRDPPluginModule >
{
public :
DECLARE_LIBID(LIBID_SocksOverRDPPluginLib)
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_SocksOverRDPPLUGIN, "{B8DC075B-7F8D-4B06-8733-7EB586CA06F0}")
};
extern class CSocksOverRDPPluginModule _AtlModule;
+25
View File
@@ -0,0 +1,25 @@
/*
* MIT License
*
* Copyright(c) 2020 Balazs Bucsay
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "stdafx.h"
+42
View File
@@ -0,0 +1,42 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#pragma once
#ifndef STRICT
#define STRICT
#endif
#include "targetver.h"
#define _ATL_APARTMENT_THREADED
#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
#define _ATL_REGISTER_PER_USER // This setting must be consistent with the project's RGS file
#include "resource.h"
//#include <afx.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
using namespace ATL;
// adtn'l includes
#include <ShlObj.h>
#include <TsVirtualChannels.h>
#include <IntSafe.h>
#include <fstream>
#include <vector>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <windows.h>
typedef std::basic_ofstream<BYTE> ByteFile;
typedef std::basic_string<WCHAR> WString;
typedef std::vector<WString> WStringVector;
+8
View File
@@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>
+643
View File
@@ -0,0 +1,643 @@
/*
* MIT License
*
* Copyright(c) 2018 Balazs Bucsay
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
TODO List:
- verbose/debug mode +others?
- anti-timeout
- check socket activity and close after timeout
*/
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <windows.h>
#include <wtsapi32.h>
#include <pchannel.h>
#include <crtdbg.h>
#include <stdio.h>
#include <strsafe.h>
#include <assert.h>
#include "SocksOverRDP-Server.h"
#include "SocksServer.h"
#pragma comment(lib, "wtsapi32.lib")
#pragma comment(lib, "Ws2_32.lib")
#define SocksOverRDP_CHANNEL_NAME "SocksChannel"
#define DEBUG_PRINT_BUFFER_SIZE 1024
#define BUF_SIZE 4096
extern DWORD WINAPI HandleClient(void *param);
DWORD OpenDynamicChannel(LPCSTR szChannelName, HANDLE *phFile);
struct arguments {
WCHAR *ip;
WCHAR *port;
BYTE priority;
} running_args;
struct threadhandles {
HANDLE hRDP = NULL;
SOCKET sock = NULL;
HANDLE pipe = NULL;
};
struct threads *ThreadHead = NULL;
int CTRLC = 0;
HANDLE ghMutex, ghLLMutex;
HANDLE hChannel;
HANDLE hWTSHandle = NULL;
BOOL bVerbose = FALSE, bDebug = FALSE;
VOID DebugPrint(HRESULT hrDbg, __in_z LPWSTR fmt, ...)
{
HRESULT hr;
TCHAR Buffer[DEBUG_PRINT_BUFFER_SIZE];
size_t Len;
hr = StringCchPrintf(Buffer, DEBUG_PRINT_BUFFER_SIZE, TEXT("[hr=0x%8x]"), hrDbg);
assert(SUCCEEDED(hr)); // buffer is sure to be big enough
hr = StringCchLength(Buffer, DEBUG_PRINT_BUFFER_SIZE, &Len);
assert(SUCCEEDED(hr)); // StringCchPrintf is supposed to always NULL term
va_list argptr;
va_start(argptr, fmt);
hr = StringCchVPrintf(Buffer + Len, DEBUG_PRINT_BUFFER_SIZE - Len,
fmt, argptr);
// the above could fail but we don't care since we
// should get a NULL terminated partial string
// insert terminating eol (despite failure)
hr = StringCchLength(Buffer, DEBUG_PRINT_BUFFER_SIZE, &Len);
assert(SUCCEEDED(hr)); // again there should be a NULL term
if (Len < DEBUG_PRINT_BUFFER_SIZE - 1)
{
Len++;
Buffer[Len] = TEXT('\0');
}
Buffer[Len - 1] = TEXT('\n');
//OutputDebugString(Buffer);
wprintf(Buffer);
}
// Add thread to linked list
struct threads *AddThread(DWORD dwThreadId, DWORD dwRemoteThreadId, HANDLE hSlot_r, HANDLE hSlot_w)
{
struct threads *rolling;
struct threads *ThreadStruct;
DWORD dwWaitResult = WaitForSingleObject(ghLLMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
ThreadStruct = (threads *)malloc(sizeof(struct threads));
ThreadStruct->dwThreadId = dwThreadId;
ThreadStruct->dwRemoteThreadId = dwRemoteThreadId;
ThreadStruct->hThread = NULL;
ThreadStruct->run = TRUE;
ThreadStruct->hSlot_r = hSlot_r;
ThreadStruct->hSlot_w = hSlot_w;
ThreadStruct->hSlot_event = NULL;
ThreadStruct->next = NULL;
if (ThreadHead == NULL)
{
ThreadHead = ThreadStruct;
}
else
{
rolling = ThreadHead;
while (rolling->next)
{
rolling = rolling->next;
}
rolling->next = ThreadStruct;
}
if (!ReleaseMutex(ghLLMutex))
{
printf("Release failed\n");
}
return ThreadStruct;
break;
case WAIT_ABANDONED:
printf("%08X: AddThread lock abandoned\n", dwThreadId);
return NULL;
}
return NULL;
}
// Look up thread and return a pointer to it by local ThreadId
struct threads *LookupThread(DWORD dwThreadId)
{
struct threads *rolling;
DWORD dwWaitResult = WaitForSingleObject(ghLLMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
rolling = ThreadHead;
if (rolling == NULL)
{
if (!ReleaseMutex(ghLLMutex))
{
DebugPrint(0, L"[-] LookupThread Release Failed0: %08X", GetCurrentThreadId());
}
return NULL;
}
while (rolling)
{
if (rolling->dwThreadId == dwThreadId)
{
if (!ReleaseMutex(ghLLMutex))
{
DebugPrint(0, L"[-] LookupThread Release Failed1: %08X", GetCurrentThreadId());
}
return rolling;
}
rolling = rolling->next;
}
if (!ReleaseMutex(ghLLMutex))
{
DebugPrint(0, L"[-] LookupThread Release Failed2: %08X", GetCurrentThreadId());
}
return NULL;
break;
case WAIT_ABANDONED:
printf("%08X: LookupThread lock abandoned\n", dwThreadId);
return NULL;
}
return NULL;
}
// Look up thread and return a pointer to it by remote threadid
struct threads *LookupThreadRemote(DWORD dwRemoteThreadId)
{
struct threads *rolling;
DWORD dwWaitResult = WaitForSingleObject(ghLLMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
rolling = ThreadHead;
if (rolling == NULL)
{
if (!ReleaseMutex(ghLLMutex))
{
DebugPrint(0, L"[-] LookupThreadRemote Release Failed0: %08X", GetCurrentThreadId());
}
return NULL;
}
while (rolling)
{
if (rolling->dwRemoteThreadId == dwRemoteThreadId)
{
if (!ReleaseMutex(ghLLMutex))
{
DebugPrint(0, L"[-] LookupThreadRemote Release Failed1: %08X", GetCurrentThreadId());
}
return rolling;
}
rolling = rolling->next;
}
if (!ReleaseMutex(ghLLMutex))
{
DebugPrint(0, L"[-] LookupThreadRemote Release Failed2: %08X", GetCurrentThreadId());
}
return NULL;
break;
case WAIT_ABANDONED:
printf("%08X: LookupThreadRemote lock abandoned\n", GetCurrentThreadId());
return NULL;
}
return NULL;
}
// Remove thread from linked list
VOID DeleteThread(DWORD dwThreadId)
{
struct threads *rolling;
struct threads *prev = NULL;
//printf("%08X: DeleteThread lock wait\n", dwThreadId);
DWORD dwWaitResult = WaitForSingleObject(ghLLMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
if (!ThreadHead)
{
if (!ReleaseMutex(ghLLMutex))
{
DebugPrint(0, L"[-] Trying to delete an empty list. %ld", GetCurrentThreadId());
}
return;
}
rolling = ThreadHead;
while (rolling->dwThreadId != dwThreadId)
{
prev = rolling;
rolling = rolling->next;
}
if (prev)
{
if (rolling->next)
{
prev->next = rolling->next;
}
else
{
prev->next = NULL;
}
}
else
{
if (ThreadHead->next)
{
ThreadHead = ThreadHead->next;
}
else
{
ThreadHead = NULL;
}
}
rolling->dwThreadId = 0xffffffff;
rolling->next = NULL;
rolling->run = FALSE;
rolling->hSlot_w = NULL;
rolling->hSlot_r = NULL;
rolling->hSlot_event = NULL;
rolling->hSlot_r = NULL;
free(rolling);
rolling = NULL;
if (!ReleaseMutex(ghLLMutex))
{
printf("Release failed\n");
}
return;
break;
case WAIT_ABANDONED:
printf("%08X: DeleteThread lock abandoned\n", dwThreadId);
return;
}
}
// If CTRL+C pressed, all threads should be stopped and safely exit
// Double press: closing channel and leaving the rest to the OS.
BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
{
struct threads *rolling;
switch (fdwCtrlType)
{
case CTRL_C_EVENT:
if (CTRLC)
{
wprintf(L"[*] Forced terminating\n");
WTSVirtualChannelClose(hWTSHandle);
exit(0);
}
wprintf(L"[*] CTRL+C pressed. Closing down.\n");
CTRLC = 1;
if (!ThreadHead)
{
WTSVirtualChannelClose(hWTSHandle);
exit(0);
}
rolling = ThreadHead;
do
{
rolling->run = FALSE;
SetEvent(rolling->hSlot_event);
} while (rolling = rolling->next);
wprintf(L"[*] All threads are signaled to stop\n");
rolling = ThreadHead;
wprintf(L"[*] Closing channel\n");
WTSVirtualChannelClose(hWTSHandle);
exit(0);
return TRUE;
default:
return FALSE;
}
}
INT _cdecl wmain(INT argc, __in_ecount(argc) WCHAR **argv)
{
WSADATA wsaData;
BOOL bSucc, ofused, bClose = FALSE;
HANDLE hEvent, hSlot_r, hSlot_w = NULL;
OVERLAPPED Overlapped, Overlapped_MailSlot;
DWORD dwRecvdLen, dwRead, dwWritten, bufWritelen, dwOverflow = 0;
DWORD dwRemoteThreadId, dwThreadId;
ULONG cbFullSize;
BYTE ReadBuffer[CHANNEL_PDU_LENGTH];
CHANNEL_PDU_HEADER *pHdr = (CHANNEL_PDU_HEADER *)ReadBuffer;
char *buf, *bufWrite, szOverflow[BUF_SIZE * 4], szMailSlotName[32];
int ret;
struct threadhandles threadhandle;
struct threads *pta;
running_args.port = L"1080";
running_args.priority = 4;
running_args.ip = L"127.0.0.1";
wprintf(L"Socks Over RDP by Balazs Bucsay [[@xoreipeip]]\n\n");
if ((ret = OpenDynamicChannel(SocksOverRDP_CHANNEL_NAME, &hChannel)) != ERROR_SUCCESS)
{
if (ret == 31)
wprintf(L"[-] Could not open Dynamic Virtual Channel, plugin was not loaded on the client side: %ld\n", ret);
else
wprintf(L"[-] Could not open Dynamic Virtual Channel: %ld %08X\n", ret, ret);
return -1;
}
wprintf(L"[*] Channel opened over RDP\n");
ghMutex = CreateMutex(NULL, FALSE, NULL);
ghLLMutex = CreateMutex(NULL, FALSE, NULL);
Overlapped_MailSlot = { 0 };
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
Overlapped = { 0 };
Overlapped.hEvent = hEvent;
if ((ret = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
{
wprintf(L"[-] WSAStartup() failed with error: %ld\n", ret);
return -1;
}
// set handler for Ctrl+C
SetConsoleCtrlHandler(CtrlHandler, TRUE);
// whatever arrives to the channel, it needs to be parsed and written to
// the corresponding mailslot
while (TRUE)
{
bSucc = ReadFile(hChannel, ReadBuffer, sizeof(ReadBuffer), &dwRead, &Overlapped);
if (!bSucc)
{
if (GetLastError() == ERROR_IO_PENDING)
{
WaitForSingleObject(Overlapped.hEvent, INFINITE);
bSucc = GetOverlappedResult(hChannel, &Overlapped, &dwRead, FALSE);
}
}
if (!bSucc)
{
wprintf(L"[-] ReadFile()/WaitForSingleObject() error: %ld\n", GetLastError());
return -1;
}
// no need to pass the header.
bufWrite = (char *)(pHdr + 1);
bufWritelen = dwRead - sizeof(CHANNEL_PDU_HEADER);
buf = (char*)bufWrite;
cbFullSize = bufWritelen;
ofused = FALSE;
// if overflow was present from previous call, we append it to the
// saved bytes
if (dwOverflow)
{
if (bDebug) printf("[*] Overflow was present from previous call. Stored bytes: %ld. Received bytes: %ld == %ld \n", dwOverflow, bufWritelen, dwOverflow+bufWritelen);
memcpy_s(szOverflow + dwOverflow, BUF_SIZE * 4, bufWrite, bufWritelen);
buf = szOverflow;
cbFullSize = bufWritelen + dwOverflow;
dwOverflow = 0;
ofused = TRUE;
}
// run while anything left in buffer
while (cbFullSize)
{
// edge case, less than necesary data in buffer
if (cbFullSize < 9)
{
if (ofused)
{
// overflow was used and still not enough data
if (bDebug) printf("[*] Not enough data, ofused: %ld\n", cbFullSize);
dwOverflow = cbFullSize;
}
else
{
// no overflow was used, saving the data to overflow
if (bDebug) printf("[*] Not enough data, no ofused: %ld\n", cbFullSize);
memcpy_s(szOverflow, BUF_SIZE * 4, buf, cbFullSize);
dwOverflow = cbFullSize;
}
// exit loop since not enough data
cbFullSize = 0;
break;
}
// parsing header
memcpy(&dwRemoteThreadId, buf, sizeof(DWORD));
memcpy(&dwRecvdLen, buf + sizeof(DWORD), sizeof(DWORD));
// corresponding thread lookup
if ((pta = LookupThreadRemote(dwRemoteThreadId)) == NULL)
{
// failed to find existing thread, creating one
memset(szMailSlotName, 0, 32);
snprintf(szMailSlotName, 32, "\\\\.\\mailslot\\RDPSocks_%08X", dwRemoteThreadId);
hSlot_r = CreateMailslotA(szMailSlotName, 0, MAILSLOT_WAIT_FOREVER, (LPSECURITY_ATTRIBUTES)NULL);
if (hSlot_r == INVALID_HANDLE_VALUE)
{
printf("CreateMailslot_r failed with %d\n", GetLastError());
break;
}
hSlot_w = CreateFileA(szMailSlotName, GENERIC_WRITE, FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
if (hSlot_w == INVALID_HANDLE_VALUE)
{
printf("CreateMailslot_w failed with %d.\n", GetLastError());
break;
}
pta = AddThread(0, dwRemoteThreadId, hSlot_r, hSlot_w);
HANDLE hDummyThread = CreateThread(
NULL,
0,
&HandleClient,
(void *)pta,
0,
&dwThreadId);
pta->dwThreadId = dwThreadId;
pta->hThread = hDummyThread;
if (bDebug) printf("[*] %08X: Thread not found, <ailslot created\n", dwRemoteThreadId);
}
else
{
if (bDebug) printf("[*] %08X: Thread found, Mailslot found\n", dwRemoteThreadId);
hSlot_w = pta->hSlot_w;
}
// Is data in buffer bigger than expected data + header?
if (dwRecvdLen <= cbFullSize - (sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE)))
{
bSucc = WriteFile(hSlot_w, buf + sizeof(DWORD) + sizeof(DWORD), dwRecvdLen + 1, &dwWritten, &Overlapped_MailSlot);
if (!bSucc)
{
if (GetLastError() == ERROR_IO_PENDING)
{
WaitForSingleObject(Overlapped_MailSlot.hEvent, INFINITE);
bSucc = GetOverlappedResult(hChannel, &Overlapped_MailSlot, &dwWritten, TRUE);
}
}
if (!bSucc)
{
if (bDebug) printf("[-] %08X: WriteChannel error: %ld\n", dwRemoteThreadId, GetLastError());
cbFullSize = 0;
}
else
{
if (bDebug) printf("[+] %08X: no error, written: %ld, should have written: %ld | cbFullSize: %ld\n", dwRemoteThreadId, dwWritten, dwRecvdLen + 1, cbFullSize);
cbFullSize -= (dwWritten + sizeof(DWORD) + sizeof(DWORD));
buf += (dwWritten + sizeof(DWORD) + sizeof(DWORD));
}
}
else
{
// less data then expected, saving to szOverflow
if (bDebug) printf("[*] !!! OVERFLOW HAPPENED %ld < %ld -9\n", dwRecvdLen, cbFullSize);
if (ofused)
{
if (bDebug) printf("[*] Data left in buffer, ofused: %ld\n", cbFullSize);
memmove_s(szOverflow, BUF_SIZE * 4, buf, cbFullSize);
dwOverflow = cbFullSize;
}
else
{
if (bDebug) printf("[*] Data left in buffer, not ofused: %ld\n", cbFullSize);
memcpy_s(szOverflow, BUF_SIZE * 4, buf, cbFullSize);
dwOverflow = cbFullSize;
}
cbFullSize = 0;
}
}
}
CloseHandle(ghMutex);
CloseHandle(hChannel);
return 0;
}
/*
* Open a dynamic channel with the name given in szChannelName.
* The output file handle can be used in ReadFile/WriteFile calls.
*/
DWORD OpenDynamicChannel(LPCSTR szChannelName, HANDLE *phFile)
{
HANDLE hWTSFileHandle;
PVOID vcFileHandlePtr = NULL;
DWORD len;
DWORD rc = ERROR_SUCCESS;
BOOL fSucc;
hWTSHandle = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, (LPSTR)szChannelName,
WTS_CHANNEL_OPTION_DYNAMIC | running_args.priority);
if (NULL == hWTSHandle)
{
rc = GetLastError();
goto exitpt;
}
fSucc = WTSVirtualChannelQuery(hWTSHandle, WTSVirtualFileHandle,
&vcFileHandlePtr, &len);
if (!fSucc)
{
rc = GetLastError();
goto exitpt;
}
if (len != sizeof(HANDLE))
{
rc = ERROR_INVALID_PARAMETER;
goto exitpt;
}
hWTSFileHandle = *(HANDLE *)vcFileHandlePtr;
fSucc = DuplicateHandle(GetCurrentProcess(), hWTSFileHandle,
GetCurrentProcess(), phFile, 0, FALSE, DUPLICATE_SAME_ACCESS);
if (!fSucc)
{
rc = GetLastError();
goto exitpt;
}
rc = ERROR_SUCCESS;
exitpt:
if (vcFileHandlePtr)
{
WTSFreeMemory(vcFileHandlePtr);
}
if (hWTSHandle)
{
WTSVirtualChannelClose(hWTSHandle);
}
return rc;
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
struct threads
{
DWORD dwThreadId;
DWORD dwRemoteThreadId;
HANDLE hThread;
BOOL run;
HANDLE hSlot_r;
HANDLE hSlot_w;
HANDLE hSlot_event;
struct threads *next;
};
struct threads *AddThread(DWORD dwThreadId, DWORD dwRemoteThreadId, HANDLE hSlot_r, HANDLE hSlot_w, HANDLE hChannel);
threads *LookupThread(DWORD dwThreadId);
threads *LookupThreadRemote(DWORD dwRemoteThreadId);
VOID DeleteThread(DWORD dwThreadId);
@@ -0,0 +1,173 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>SocksOverRDPServer</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="SocksOverRDP-Server.h" />
<ClInclude Include="SocksServer.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="SocksServer.cpp" />
<ClCompile Include="SocksOverRDP-Server.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SocksServer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SocksOverRDP-Server.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="SocksOverRDP-Server.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SocksServer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+639
View File
@@ -0,0 +1,639 @@
/*
TODO: check closing flag at negotiation phases - two functions.
TODO: slotevent hslot passed from socksoverrdp-server.cpp
*/
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <windows.h>
#include <stdio.h>
#include <process.h>
#include "SocksServer.h"
#include "SocksOverRDP-Server.h"
#pragma comment(lib, "Ws2_32.lib")
#define METHOD_NUMBER 1
#define BUF_SIZE 4096
// hardcoded inactive creds, use proper creds check if you want this
#define PREDEF_USERNAME "hello"
#define PREDEF_PASSWORD "bello"
extern threads *LookupThread(DWORD dwThreadId);
extern VOID DeleteThread(DWORD dwThreadId);
extern HANDLE ghMutex;
extern HANDLE hChannel;
extern BOOL bVerbose, bDebug;
int method_no_auth_required(HANDLE c, int count, char *rv);
typedef int(*fn)(HANDLE, int, char*);
static fn method_functions[METHOD_NUMBER] =
{
method_no_auth_required,
// method_username_password, // disabled for security purposes
};
static char method_numbers[METHOD_NUMBER] =
{
0,
// 2,
};
int method_no_auth_required(HANDLE c, int count, char *rv)
{
return TRUE;
}
// dedicated function to handle writes on the virtual channel
BOOL WriteChannel(char *Buffer, DWORD nBytesToWrite, DWORD *nBytesWrittes, DWORD dwRemoteThreadId, BOOL bClose)
{
HANDLE hEvent;
OVERLAPPED Overlapped;
DWORD i, dwLimit, dwToWrite, dwLocalSent, dwWaitResult;
DWORD dwHeaderSize = sizeof(DWORD) + sizeof(DWORD) + sizeof(BYTE);
BOOL bSucc = FALSE;
dwToWrite = BUF_SIZE;
dwLocalSent = 0;
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
Overlapped = { 0 };
Overlapped.hEvent = hEvent;
// number of writes
dwLimit = (unsigned int)ceil(nBytesToWrite / (double)BUF_SIZE);
// no content but close connection request.
if (!dwLimit && bClose)
dwLimit = 1;
// mandatory header with
memcpy_s(Buffer - dwHeaderSize, 4, &dwRemoteThreadId, sizeof(DWORD));
memcpy_s(Buffer + sizeof(DWORD) - dwHeaderSize, 4, &dwToWrite, sizeof(DWORD));
Buffer[sizeof(DWORD) + sizeof(DWORD) - dwHeaderSize] = 0;
dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
for (i = 0; i < dwLimit; i++)
{
if (i == dwLimit - 1)
{
dwToWrite = nBytesToWrite % (BUF_SIZE + 1);
memcpy_s(Buffer + sizeof(DWORD) - 9, 4, &dwToWrite, sizeof(DWORD));
if (bClose) Buffer[sizeof(DWORD) + sizeof(DWORD) - 9] = 0x01;
}
//printf("%08X: CHANNEL Sent: %ld content length: %ld\n", dwRemoteThreadId, dwToWrite + 9, dwToWrite);
bSucc = WriteFile(hChannel, Buffer - 9, dwToWrite + 9, &dwLocalSent, &Overlapped);
if (!bSucc)
{
if (GetLastError() == ERROR_IO_PENDING)
{
WaitForSingleObject(Overlapped.hEvent, INFINITE);
bSucc = GetOverlappedResult(hChannel, &Overlapped, &dwLocalSent, TRUE);
}
}
if (!bSucc)
{
if (bVerbose) printf("[-] hChannel thread(%08X) WriteChannel: %ld\n", GetCurrentThreadId(), GetLastError());
if (!ReleaseMutex(ghMutex))
{
printf("Release failed1\n");
}
return FALSE;
}
*nBytesWrittes += dwLocalSent;
}
if (!ReleaseMutex(ghMutex))
{
printf("Release failed2\n");
}
return bSucc;
break;
case WAIT_ABANDONED:
return FALSE;
}
return bSucc;
}
int CheckAuthentication(char *buf_full, int ret)
{
DWORD i, j, dwWritten = 2;
char *answer, *buf, answer_tosend[2 + sizeof(DWORD) + sizeof(DWORD) + 1];
struct threads *pta;
buf = buf_full + 1;
answer = answer_tosend + sizeof(DWORD) + sizeof(DWORD) + 1;
pta = LookupThread(GetCurrentThreadId());
answer[0] = 5;
for (i = 0; i < METHOD_NUMBER; i++)
for (j = 0; j < (unsigned char)buf[1]; j++)
if (buf[j + 2] == method_numbers[i])
{
answer[1] = method_numbers[i];
WriteChannel(answer, 2, &dwWritten, pta->dwRemoteThreadId, FALSE);
return i;
}
answer[1] = (unsigned)0xFF;
WriteChannel(answer, 2, &dwWritten, pta->dwRemoteThreadId, FALSE);
return -1;
}
void sendReply(char replyField, char addressType, char *addr, char *port)
{
char null[20], *answer, answer2[300 + sizeof(DWORD) + sizeof(DWORD) + 1];
DWORD dwWritten, ret;
struct threads *pta;
answer = answer2 + sizeof(DWORD) + sizeof(DWORD) + 1;
memset(answer, 0, 300 + sizeof(DWORD) + sizeof(DWORD) + 1);
memset(null, 0, 20);
pta = LookupThread(GetCurrentThreadId());
// if addr or port set to NULL, we will send nulls instead of the address
// it isn't RFC compliant but I do not support info leak either.
if (addr == NULL) addr = null;
if (port == NULL) port = null;
answer[0] = 5;
answer[1] = replyField;
answer[3] = addressType;
switch (addressType)
{
case 3:
memcpy_s(answer + 4, 296, (void *)(addr + 1), (unsigned char)(addr[0]));
memcpy_s(answer + 4 + (unsigned char)(addr[0]), 396 - (unsigned char)(addr[0]), port, 2);
ret = (unsigned char)(addr[0]) + 2;
break;
case 4:
memcpy_s(answer + 4, 296, addr, 16);
memcpy_s(answer + 20, 280, port, 2);
ret = 22;
break;
default:
memcpy_s(answer + 4, 296, addr, 4);
memcpy_s(answer + 8, 292, port, 2);
ret = 10;
break;
}
if (replyField == 0x00)
WriteChannel(answer, ret, &dwWritten, pta->dwRemoteThreadId, FALSE);
else
WriteChannel(answer, ret, &dwWritten, pta->dwRemoteThreadId, TRUE);
}
int getAddressInfo(sockaddr_in *sockaddrin, sockaddr_in6 *sockaddrin6, char *buf, int ret)
{
ADDRINFOA hints;
ADDRINFOA *result = NULL;
char domain[256];
//IPv4
if (buf[3] == 1)
{
if (ret != 10)
{
if (bVerbose) printf("[-] SOCKS thread(%08Xd) getAddressInfo IPv4 selected, length mismatch: %ld\n", GetCurrentThreadId(), ret);
return -1;
}
sockaddrin->sin_family = AF_INET;
memcpy_s(&(sockaddrin->sin_port), 2, buf + 8, 2);
memcpy_s(&(sockaddrin->sin_addr), 4, buf + 4, 4);
char *s = (char *)malloc(INET_ADDRSTRLEN);
inet_ntop(AF_INET, &(sockaddrin->sin_addr), s, INET_ADDRSTRLEN);
if (bVerbose) printf("[+] SOCKS thread(%08X) getAddressInfo CONNECT IPv4: %s:%hd\n", GetCurrentThreadId(), s, htons(sockaddrin->sin_port));
free(s);
}
//DNS
if (buf[3] == 3)
{
if ((7 + (unsigned char)buf[4]) != ret)
{
if (bVerbose) printf("[-] SOCKS thread(%08X) getAddressInfo DNS selected, length mismatch: %ld\n", GetCurrentThreadId(), ret);
return -1;
}
ZeroMemory(&hints, sizeof(hints));
ZeroMemory(domain, 256);
// change for IPv6?
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
memcpy_s(domain, 256, (void *)(buf + 5), (unsigned char)(buf[4]));
if ((ret = GetAddrInfoA(domain, "1", &hints, &result)) != 0) {
if (bVerbose) printf("[-] SOCKS thread(%08X) getAddressInfo GetAddrInfoA failed with error: %ld %ld\n", GetCurrentThreadId(), ret, WSAGetLastError());
return -1;
}
memcpy_s(sockaddrin, sizeof(sockaddr_in), result->ai_addr, sizeof(sockaddr_in));
memcpy_s(&(sockaddrin->sin_port), 2, buf + ((unsigned char)buf[4]) + 5, 2);
char *s = (char *)malloc(INET_ADDRSTRLEN);
inet_ntop(AF_INET, &(sockaddrin->sin_addr), s, INET_ADDRSTRLEN);
if (bVerbose) printf("[+] SOCKS thread(%08X) getAddressInfo CONNECT DNS: %s(%s):%hd\n", GetCurrentThreadId(), domain, s, htons(sockaddrin->sin_port));
free(s);
}
//IPv6
if (buf[3] == 4)
{
if (ret != 22)
{
if (bVerbose) printf("[-] SOCKS thread(%08X) getAddressInfo IPv6 selected, length mismatch: %ld\n", GetCurrentThreadId(), ret);
return -1;
}
sockaddrin6->sin6_family = AF_INET6;
memcpy_s(&(sockaddrin6->sin6_port), 2, buf + 20, 2);
memcpy_s(&(sockaddrin6->sin6_addr), 30, buf + 4, 16);
char *s = (char *)malloc(INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &(sockaddrin6->sin6_addr), s, INET6_ADDRSTRLEN);
if (bVerbose) printf("[+] SOCKS thread(%08X) getAddressInfo CONNECT IPv6: %s:%hd\n", GetCurrentThreadId(), s, htons(sockaddrin6->sin6_port));
free(s);
}
return 0;
}
SOCKET DoConnection(char *buf, int ret)
{
SOCKET sock;
sockaddr_in sockaddrin;
sockaddr_in6 sockaddrin6;
if (buf[0] == 5)
{
if (getAddressInfo(&sockaddrin, &sockaddrin6, buf, ret) < 0) {
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection could not create socket structs\n", GetCurrentThreadId());
// this isnt "general SOCKS server failure", but there no better error code
sendReply(0x01, 0x01, NULL, NULL);
return NULL;
}
// CONNECT
if (buf[1] == 1)
{
if (buf[3] == 4)
{
if ((sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection socket6() failed with: %ld\n", GetCurrentThreadId(), WSAGetLastError());
sendReply(0x01, 0x04, NULL, NULL);
return NULL;
}
if ((ret = connect(sock, (SOCKADDR *)&sockaddrin6, sizeof(sockaddrin6))) == SOCKET_ERROR) {
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection connect6() failed with: %ld\n", GetCurrentThreadId(), WSAGetLastError());
sendReply(0x05, 0x04, NULL, NULL);
return NULL;
}
}
else
{
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection socket() failed with: %ld\n", GetCurrentThreadId(), WSAGetLastError());
sendReply(0x01, 0x01, NULL, NULL);
return NULL;
}
if ((ret = connect(sock, (SOCKADDR *)&sockaddrin, sizeof(sockaddrin))) == SOCKET_ERROR) {
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection connect() failed with: %ld\n", GetCurrentThreadId(), WSAGetLastError());
sendReply(0x05, 0x01, NULL, NULL);
return NULL;
}
}
sendReply(0x00, 0x01, NULL, NULL);
return sock;
}
// BIND
if (buf[1] == 2)
{
printf("[+] SOCKS DoConnection BIND\n");
}
// UDP ASSOCIATE
if (buf[1] == 3)
{
//SOCK_DGRAM
printf("[+] SOCKS DoConnection UDP ASSOCIATE\n");
}
}
else
{
if (bVerbose) printf("[-] SOCKS thread(%08X) DoConnection unknown SOCKS version\n", GetCurrentThreadId());
return NULL;
}
return NULL;
}
// Thread's main function that handles all communication of the corresponding
// connection. It's remote ThreadID attribute matches the server's threadID
// which will be used to track the connections.
DWORD WINAPI HandleClient(void *param)
{
struct threads *pta = (struct threads *)param;
WSANETWORKEVENTS NetworkEvents;
WSAOVERLAPPED SendOverlapped;
OVERLAPPED Overlapped_MailSlot;
HANDLE hEvents[2], hMailSlot = pta->hSlot_r;
DWORD dwRet, dwRecvN, dwSentN, dwSentPointer, Flags;
SOCKET sRelayConnection;
BOOL bClose = FALSE;
WSABUF DataBuf;
char buf[BUF_SIZE + 1];
int rc, iSrecvN, iAuthNum = -1;
Overlapped_MailSlot = { 0 };
// socks basics
if (ReadFile(hMailSlot, buf, BUF_SIZE + 1, &dwRet, NULL))
{
if (buf[0] == 0x01)
goto exitthread;
if (buf[1] == 4)
{
//socks4
if (bDebug) printf("%08X: SOCKS HandleClient Socks4 request\n", pta->dwRemoteThreadId);
goto exitthread;
}
else
if (buf[1] == 5)
{
// socks5
if (dwRet - 3 != buf[2])
{
if (bDebug) printf("%08X: SOCKS HandleClient wrong list length: %ld\n", pta->dwRemoteThreadId, dwRet);
goto exitthread;
}
if ((iAuthNum = CheckAuthentication(buf, dwRet)) < 0)
{
if (bDebug) printf("%08X: SOCKS HandleClient auth failed: %ld\n", pta->dwRemoteThreadId, iAuthNum);
goto exitthread;
}
}
else
{
if (bDebug)
{
printf("%08X: SOCKS HandleClient unknown Socks version number\n", pta->dwRemoteThreadId);
printf("%08X: Readfile ret: %ld\n", pta->dwRemoteThreadId, dwRet);
for (DWORD i = 0; i < dwRet; i++)
printf("%02X ", (unsigned char)buf[i]);
printf("\n");
}
goto exitthread;
}
}
else
{
if (bDebug) printf("%08X: SOCKS HandleClient while ReadFile error: %ld\n", pta->dwRemoteThreadId, GetLastError());
goto exitthread;
}
if (iAuthNum == -1)
{
if (bDebug) printf("%08X: SOCKS HandleClient wrong authnum: %ld\n", pta->dwRemoteThreadId, iAuthNum);
goto exitthread;
}
// socks authentication
if (iAuthNum > 0)
{
if (bDebug) printf("%08X: SOCKS HandleClient authentication invoked: %ld\n", pta->dwRemoteThreadId, iAuthNum);
if (ReadFile(hMailSlot, buf, BUF_SIZE, &dwRet, NULL))
{
if (dwRet > 2)
{
if (!method_functions[iAuthNum](hMailSlot, dwRet, buf))
{
if (bDebug) printf("%08X: SOCKS HandleClient authentication failed: %ld\n", pta->dwRemoteThreadId, iAuthNum);
goto exitthread;
}
}
else
{
if (bDebug) printf("%08X: SOCKS HandleClient less than 2 recv error: %ld %ld\n", pta->dwRemoteThreadId, dwRet, WSAGetLastError());
goto exitthread;
}
}
else
{
if (bDebug) printf("%08X: SOCKS HandleClient authentication recv error: %ld %ld\n", pta->dwRemoteThreadId, dwRet, WSAGetLastError());
goto exitthread;
}
}
// socks connection phase
if (ReadFile(hMailSlot, buf, BUF_SIZE, &dwRet, NULL))
{
if (dwRet > 0)
if (buf[0] == 0x01)
goto exitthread;
if (dwRet > 6)
{
if ((sRelayConnection = DoConnection(buf + 1, dwRet - 1)) == NULL)
{
if (bDebug) printf("%08X: SOCKS HandleClient no socket created\n", pta->dwRemoteThreadId);
goto exitthread;
}
}
else
{
if (bDebug) printf("%08X: SOCKS HandleClient connection request less than 6 error: %ld %ld\n", pta->dwRemoteThreadId, dwRet, WSAGetLastError());
goto exitthread;
}
}
else
{
if (bDebug) printf("%08X: SOCKS HandleClient connection request recv error: %ld %ld\n", pta->dwRemoteThreadId, dwRet, WSAGetLastError());
goto exitthread;
}
hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
hEvents[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
pta->hSlot_event = hEvents[0];
Overlapped_MailSlot.hEvent = hEvents[0];
SecureZeroMemory((PVOID)& SendOverlapped, sizeof(WSAOVERLAPPED));
SendOverlapped.hEvent = WSACreateEvent();
if (SendOverlapped.hEvent == NULL) {
printf("Mailslot thread(%08X) WSACreateEvent failed with error: %d\n", pta->dwRemoteThreadId, WSAGetLastError());
goto exitthread;
}
if ((hEvents[0] == NULL) || ((hEvents[1] == NULL)))
{
printf("[-] Mailslot thread(%08X) CreateEvent failed with %ld\n", pta->dwRemoteThreadId, GetLastError());
goto exitthread;
}
WSAEventSelect(sRelayConnection, hEvents[1], FD_READ | FD_CLOSE);
BOOL read = true;
while (pta->run)
{
if (read)
{
if (ReadFile(hMailSlot, buf, BUF_SIZE + 1, &dwRecvN, &Overlapped_MailSlot) == FALSE)
{
if (GetLastError() != ERROR_IO_PENDING)
{
printf("[-] Mailslot thread(%08X) ReadFile error %ld\n", pta->dwRemoteThreadId, GetLastError());
pta->run = FALSE;
break;
}
}
read = FALSE;
}
dwRet = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
if ((dwRet - WAIT_OBJECT_0) < 0 || (dwRet - WAIT_OBJECT_0) > (2 - 1))
{
printf("[-] Mailslot thread(%08X) WaitForMultipleObjects index out of range %ld\n", pta->dwRemoteThreadId, dwRet);
pta->run = FALSE;
break;
}
if (pta->run == FALSE)
{
break;
}
switch (dwRet - WAIT_OBJECT_0)
{
case 0:
if (bDebug) printf("%08X: READ recvn: %ld - internalhigh: %ld - internal: %ld\n", pta->dwRemoteThreadId, dwRecvN, Overlapped_MailSlot.InternalHigh, Overlapped_MailSlot.Internal);
dwRecvN = Overlapped_MailSlot.InternalHigh;
if (buf[0] == 0x01)
{
pta->run = FALSE;
}
dwSentPointer = 1;
while (dwSentPointer < dwRecvN)
{
if (!pta->run)
{
//printf("%08X: was set to exit1\n", pta->dwRemoteThreadId);
break;
}
DataBuf.len = dwRecvN - dwSentPointer;
DataBuf.buf = buf + dwSentPointer;
rc = WSASend(sRelayConnection, &DataBuf, 1, &dwSentN, NULL, &SendOverlapped, NULL);
if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != WSAGetLastError()))
{
printf("[-] Mailslot thread(%08X) WSASend failed with error: %d\n", pta->dwRemoteThreadId, WSAGetLastError());
pta->run = FALSE;
break;
}
rc = WSAWaitForMultipleEvents(1, &SendOverlapped.hEvent, TRUE, INFINITE, TRUE);
if (rc == WSA_WAIT_FAILED)
{
printf("[-] Mailslot thread(%08X) WSAWaitForMultipleEvents failed with error: %d\n", pta->dwRemoteThreadId, WSAGetLastError());
pta->run = FALSE;
break;
}
rc = WSAGetOverlappedResult(sRelayConnection, &SendOverlapped, &dwSentN, FALSE, &Flags);
if (rc == FALSE)
{
printf("[-] Mailslot thread(%08X) WSASend failed with error: %d\n", pta->dwRemoteThreadId, WSAGetLastError());
pta->run = FALSE;
break;
}
WSAResetEvent(SendOverlapped.hEvent);
dwSentPointer += dwSentN;
}
read = TRUE;
break;
case 1:
if (WSAEnumNetworkEvents(sRelayConnection, hEvents[1], &NetworkEvents) == SOCKET_ERROR) {
printf("[-] SOCKS thread(%08X) HandleClient WSAEnumNetworkEvents error: %ld\n", pta->dwRemoteThreadId, GetLastError());
}
else
{
if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
if (bDebug) printf("%08X: bClose FD_CLOSE was set\n", pta->dwRemoteThreadId);
bClose = TRUE;
}
}
do
{
if ((iSrecvN = recv(sRelayConnection, buf + sizeof(DWORD) + sizeof(DWORD) + 1, BUF_SIZE, 0)) > 0)
{
if (bDebug) printf("%08X: RECV recvn: %ld\n", pta->dwRemoteThreadId, iSrecvN);
dwSentPointer = 0;
if (!WriteChannel(buf + sizeof(DWORD) + sizeof(DWORD) + 1, iSrecvN, &dwSentPointer, pta->dwRemoteThreadId, FALSE))
{
pta->run = FALSE;
}
}
else
{
bClose = TRUE;
}
// run again the loop only if there is more data and the last data packet was set to FIN
} while (bClose && (iSrecvN > 0));
if (bClose)
{
if (bDebug) printf("%08X: CLOSE\n", pta->dwRemoteThreadId);
if (!WriteChannel(buf + sizeof(DWORD) + sizeof(DWORD) + 1, 0, &dwSentPointer, pta->dwRemoteThreadId, TRUE))
printf("[-] Mailslot thread(%08X) HandleClient select1 WriteChannel error: %ld %ld\n", pta->dwRemoteThreadId, dwSentN, GetLastError());
// FIN recv'd
if (iSrecvN == SOCKET_ERROR)
{
if (bVerbose) printf("[-] SOCKS thread(%08X) HandleClient select1 recv error: %ld %ld\n", pta->dwRemoteThreadId, iSrecvN, WSAGetLastError());
}
pta->run = FALSE;
}
break;
default:
break;
}
}
WSACloseEvent(SendOverlapped.hEvent);
exitthread:
// closing down the thread
shutdown(sRelayConnection, SD_SEND);
CloseHandle(pta->hSlot_r);
CloseHandle(pta->hSlot_w);
CloseHandle(hEvents[0]);
CloseHandle(hEvents[1]);
DeleteThread(GetCurrentThreadId());
return 0;
}
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
int StartServer(WCHAR *ip, WCHAR *port);
+8
View File
@@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>