C++ 端口监视器 (mfilemon.dll) RDP 虚拟通道代码未执行
C++ Port Monitor (mfilemon.dll) RDP Virtual Channel code not executing
我最近开始使用开源 mfilemon.dll 并尝试向其添加其他功能。
我要添加的功能是通过虚拟通道传输数据。我写了一个小的控制台 exe 来测试代码,我在下面成功发送了数据(我在另一边收到了一个消息弹出窗口)。
当此代码放入 mfilemon.dll 时,没有任何反应。 DLL 的所有其他功能都正常工作,但只是没有执行此代码。我认为后台处理程序服务以及 windows 中的某些内容正在阻止某些 API 调用,但很高兴能确定。
这是我编写的 exe 代码,它成功地通过我的虚拟通道发送数据(我的项目是针对 Win8.1 的,所以我必须将 legacy_stdio_definitions.lib
添加到链接器输入文件)。
#include "stdafx.h"
#include "conio.h"
#include "iostream"
struct IUnknown; // Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here" when using /permissive-
#include "windows.h"
#include "WtsApi32.h"
#pragma comment(lib, "wtsapi32.lib")
int main()
{
std::cout << "Testing";
const char* data = "You just printed data!";
HANDLE mHandle;
mHandle = WTSVirtualChannelOpen(NULL, (DWORD)-1, (LPSTR)"PRINTWP");
PULONG written = 0;
bool ret = WTSVirtualChannelWrite(mHandle, (PCHAR)data, 22, written);
if (!ret || written == (PULONG)13)
{
}
else
{
}
ret = WTSVirtualChannelClose(mHandle);
_getch();
return 0;
}
这是我的虚拟频道DLL代码。
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <Shellapi.h>
#include <Cchannel.h> // Contains the definition for PCHANNEL_ENTRY_POINTS
#include <string.h>
#include <winspool.h>
#include <fstream>
#include <iostream>
PCHANNEL_ENTRY_POINTS gpEntryPoints;
LPHANDLE gphChannel;
void VCAPITYPE VirtualChannelInitEventProc(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength);
void VCAPITYPE VirtualChannelOpenEvent_PRINTWP(DWORD openHandle, UINT event, LPVOID pdata, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags);
DWORD gdwOpenChannel_PRINTWP;
const char* channel_PRINTWP = "PRINTWP";
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
MessageBox(NULL, TEXT("RDP Virtual channel DLL Loaded."), TEXT("Hosted Channel"), MB_OK);
gpEntryPoints = (PCHANNEL_ENTRY_POINTS)LocalAlloc(LPTR, pEntryPoints->cbSize);
CopyMemory(gpEntryPoints, pEntryPoints, pEntryPoints->cbSize);
UINT rc_channel;
CHANNEL_DEF channel_def[1]; // This is where you can increase the number of registered virtual channels assuming you define them later.
ZeroMemory(&channel_def[0], sizeof(CHANNEL_DEF));
CopyMemory(channel_def[0].name, channel_PRINTWP, strlen(channel_PRINTWP));
rc_channel = gpEntryPoints->pVirtualChannelInit((LPVOID *)&gphChannel, channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, (PCHANNEL_INIT_EVENT_FN)VirtualChannelInitEventProc);
if (rc_channel != CHANNEL_RC_OK)
{
MessageBox(NULL, TEXT("RDP Virtual Channel registration has failed!"),TEXT("Channel Message"), MB_OK);
return FALSE;
}
if (channel_def[0].options != CHANNEL_OPTION_INITIALIZED)
{
MessageBox(NULL, TEXT("RDP Virtual Channel options initialization failure!"), TEXT("Channel Message"), MB_OK);
return FALSE;
}
MessageBox(NULL, TEXT("RDP Virtual Channel initialized."), TEXT("Channel Message"), MB_OK);
return TRUE;
}
void VCAPITYPE VirtualChannelInitEventProc(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
UINT rc_channel_HLINK;
UINT rc_channel_PREVIEW;
UINT rc_channel_PRINTWP;
switch (event)
{
case CHANNEL_EVENT_INITIALIZED:
break;
case CHANNEL_EVENT_CONNECTED:
rc_channel_PRINTWP = gpEntryPoints->pVirtualChannelOpen(gphChannel, &gdwOpenChannel_PRINTWP, (PCHAR)channel_PRINTWP, (PCHANNEL_OPEN_EVENT_FN)VirtualChannelOpenEvent_PRINTWP);
if (rc_channel_PRINTWP != CHANNEL_RC_OK)
{
MessageBox(NULL, TEXT("Open of RDP virtual channel failed"), TEXT("Channel Message"), MB_OK);
}
else
{
MessageBox(NULL, TEXT("Open of RDP virtual channel success"), TEXT("Channel Message"), MB_OK);
}
break;
case CHANNEL_EVENT_V1_CONNECTED:
MessageBox(NULL, TEXT("Connecting to a non Windows 2000 Terminal Server"), TEXT("Channel Message"), MB_OK);
break;
case CHANNEL_EVENT_DISCONNECTED:
break;
case CHANNEL_EVENT_TERMINATED:
LocalFree((HLOCAL)gpEntryPoints);
break;
default:
break;
}
}
void VCAPITYPE VirtualChannelOpenEvent_PRINTWP(DWORD openHandle, UINT event, LPVOID pdata, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
MessageBox(NULL, TEXT("Data received."), TEXT("Channel Message"), MB_OK);
char* data;
data = (char*)malloc(dataLength + 1);
CopyMemory(data, pdata, dataLength);
data[dataLength] = '[=12=]';
MessageBoxA(NULL, data, "PRINTWP", MB_OK);
free(data);
break;
default:
break;
}
}
def 文件:
LIBRARY FrzHostedChannel
EXPORTS
VirtualChannelEntry
dllmain:
#include "stdafx.h"
使用上述代码需要更改注册表,以便 mstsc.exe 知道加载此插件。
如果有人熟悉端口监视器和执行除创建文件之外的其他操作的代码,那就太棒了。
Spoolsv.exe 是一项服务,因此在与通过 RDP 连接的会话不同的会话中运行。使用的任何 DLL 和生成的子进程也是该会话的一部分。
mHandle = WTSVirtualChannelOpen(NULL, (DWORD)-1, (LPSTR)"PRINTWP");
需要将 (DWORD)-1
更改为通过 RDP 连接的实际会话。
我最近开始使用开源 mfilemon.dll 并尝试向其添加其他功能。
我要添加的功能是通过虚拟通道传输数据。我写了一个小的控制台 exe 来测试代码,我在下面成功发送了数据(我在另一边收到了一个消息弹出窗口)。
当此代码放入 mfilemon.dll 时,没有任何反应。 DLL 的所有其他功能都正常工作,但只是没有执行此代码。我认为后台处理程序服务以及 windows 中的某些内容正在阻止某些 API 调用,但很高兴能确定。
这是我编写的 exe 代码,它成功地通过我的虚拟通道发送数据(我的项目是针对 Win8.1 的,所以我必须将 legacy_stdio_definitions.lib
添加到链接器输入文件)。
#include "stdafx.h"
#include "conio.h"
#include "iostream"
struct IUnknown; // Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here" when using /permissive-
#include "windows.h"
#include "WtsApi32.h"
#pragma comment(lib, "wtsapi32.lib")
int main()
{
std::cout << "Testing";
const char* data = "You just printed data!";
HANDLE mHandle;
mHandle = WTSVirtualChannelOpen(NULL, (DWORD)-1, (LPSTR)"PRINTWP");
PULONG written = 0;
bool ret = WTSVirtualChannelWrite(mHandle, (PCHAR)data, 22, written);
if (!ret || written == (PULONG)13)
{
}
else
{
}
ret = WTSVirtualChannelClose(mHandle);
_getch();
return 0;
}
这是我的虚拟频道DLL代码。
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <Shellapi.h>
#include <Cchannel.h> // Contains the definition for PCHANNEL_ENTRY_POINTS
#include <string.h>
#include <winspool.h>
#include <fstream>
#include <iostream>
PCHANNEL_ENTRY_POINTS gpEntryPoints;
LPHANDLE gphChannel;
void VCAPITYPE VirtualChannelInitEventProc(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength);
void VCAPITYPE VirtualChannelOpenEvent_PRINTWP(DWORD openHandle, UINT event, LPVOID pdata, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags);
DWORD gdwOpenChannel_PRINTWP;
const char* channel_PRINTWP = "PRINTWP";
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
MessageBox(NULL, TEXT("RDP Virtual channel DLL Loaded."), TEXT("Hosted Channel"), MB_OK);
gpEntryPoints = (PCHANNEL_ENTRY_POINTS)LocalAlloc(LPTR, pEntryPoints->cbSize);
CopyMemory(gpEntryPoints, pEntryPoints, pEntryPoints->cbSize);
UINT rc_channel;
CHANNEL_DEF channel_def[1]; // This is where you can increase the number of registered virtual channels assuming you define them later.
ZeroMemory(&channel_def[0], sizeof(CHANNEL_DEF));
CopyMemory(channel_def[0].name, channel_PRINTWP, strlen(channel_PRINTWP));
rc_channel = gpEntryPoints->pVirtualChannelInit((LPVOID *)&gphChannel, channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, (PCHANNEL_INIT_EVENT_FN)VirtualChannelInitEventProc);
if (rc_channel != CHANNEL_RC_OK)
{
MessageBox(NULL, TEXT("RDP Virtual Channel registration has failed!"),TEXT("Channel Message"), MB_OK);
return FALSE;
}
if (channel_def[0].options != CHANNEL_OPTION_INITIALIZED)
{
MessageBox(NULL, TEXT("RDP Virtual Channel options initialization failure!"), TEXT("Channel Message"), MB_OK);
return FALSE;
}
MessageBox(NULL, TEXT("RDP Virtual Channel initialized."), TEXT("Channel Message"), MB_OK);
return TRUE;
}
void VCAPITYPE VirtualChannelInitEventProc(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
UINT rc_channel_HLINK;
UINT rc_channel_PREVIEW;
UINT rc_channel_PRINTWP;
switch (event)
{
case CHANNEL_EVENT_INITIALIZED:
break;
case CHANNEL_EVENT_CONNECTED:
rc_channel_PRINTWP = gpEntryPoints->pVirtualChannelOpen(gphChannel, &gdwOpenChannel_PRINTWP, (PCHAR)channel_PRINTWP, (PCHANNEL_OPEN_EVENT_FN)VirtualChannelOpenEvent_PRINTWP);
if (rc_channel_PRINTWP != CHANNEL_RC_OK)
{
MessageBox(NULL, TEXT("Open of RDP virtual channel failed"), TEXT("Channel Message"), MB_OK);
}
else
{
MessageBox(NULL, TEXT("Open of RDP virtual channel success"), TEXT("Channel Message"), MB_OK);
}
break;
case CHANNEL_EVENT_V1_CONNECTED:
MessageBox(NULL, TEXT("Connecting to a non Windows 2000 Terminal Server"), TEXT("Channel Message"), MB_OK);
break;
case CHANNEL_EVENT_DISCONNECTED:
break;
case CHANNEL_EVENT_TERMINATED:
LocalFree((HLOCAL)gpEntryPoints);
break;
default:
break;
}
}
void VCAPITYPE VirtualChannelOpenEvent_PRINTWP(DWORD openHandle, UINT event, LPVOID pdata, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
MessageBox(NULL, TEXT("Data received."), TEXT("Channel Message"), MB_OK);
char* data;
data = (char*)malloc(dataLength + 1);
CopyMemory(data, pdata, dataLength);
data[dataLength] = '[=12=]';
MessageBoxA(NULL, data, "PRINTWP", MB_OK);
free(data);
break;
default:
break;
}
}
def 文件:
LIBRARY FrzHostedChannel
EXPORTS
VirtualChannelEntry
dllmain:
#include "stdafx.h"
使用上述代码需要更改注册表,以便 mstsc.exe 知道加载此插件。
如果有人熟悉端口监视器和执行除创建文件之外的其他操作的代码,那就太棒了。
Spoolsv.exe 是一项服务,因此在与通过 RDP 连接的会话不同的会话中运行。使用的任何 DLL 和生成的子进程也是该会话的一部分。
mHandle = WTSVirtualChannelOpen(NULL, (DWORD)-1, (LPSTR)"PRINTWP");
需要将 (DWORD)-1
更改为通过 RDP 连接的实际会话。