C ++ Port Monitor (mfilemon.dll) Код виртуального канала RDP не выполняется - PullRequest
0 голосов
/ 09 мая 2018

Я недавно начал работать с открытым исходным кодом 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] = '\0';

        MessageBoxA(NULL, data, "PRINTWP", MB_OK);

        free(data);

        break;

    default:
        break;
    }
}

файл определения:

LIBRARY FrzHostedChannel
EXPORTS
VirtualChannelEntry

DllMain:

#include "stdafx.h"

Использование этого кода выше требует изменения реестра, поэтому mstsc.exe знает, как загрузить этот плагин.

Если кто-то знаком с мониторами портов и выполняет код, который делает что-то, кроме создания файла, это было бы здорово.

1 Ответ

0 голосов
/ 11 мая 2018

Spoolsv.exe является службой и, следовательно, работает в сеансе, который НЕ совпадает с сеансом, подключенным через RDP.Любые используемые библиотеки DLL и порожденные дочерние процессы также являются частью этого сеанса.

mHandle = WTSVirtualChannelOpen(NULL, (DWORD)-1, (LPSTR)"PRINTWP");

(DWORD)-1 необходимо изменить на фактический сеанс, подключенный через RDP.

...