EasyHook, .NET Remoting Интерфейс обмена между клиентом и сервером?

Как можети то и другое клиент IPC и сервер IPC вызывают общедоступный интерфейс удаленного взаимодействия (класс, наследующий MarshalByRefObject), чтобы обмениваться данными, без необходимости помещать класс интерфейса внутри приложения для инъекций? Например, если я поместил класс интерфейса ввведенный библиотечный проект, который внедряется в мой целевой процесс, мое приложение для инъекций не может ссылаться на этот интерфейс.

Изменить: я ответил на вопрос ниже.

Ответы на вопрос(1)

Решение Вопроса

EasyHook Commit 66751 (привязанный к EasyHook 2.7 alpha), он неКажется возможным получить экземпляр интерфейса удаленного взаимодействия в обоих клиентах (этот процесс, которыйначатый инъекция вашей DLL) и сервер (введенный процесс запуска вашей внедренной DLL).

Что я имею в виду?

Ну, вFileMon а такжеProcessMonitor примеры, обратите внимание, как разделяют удаленные интерфейсы (FileMonInterface, встроенный вProgram.cs, заФилемон, а такжеDemoInterface, в своем собственном файле, дляProcessMonitor) размещены винъекционных сборка.FileMonInterface находится в проекте FileMon.DemoInterface находится в проекте ProcessMonitor.

Почему не другой раунд? Почему бы не поставитьFileMonInterface в проекте FileMonInject, и положитьDemoInterface в ProcMonInject?Потому что тогда интерфейсы больше не будут доступны для вызывающих приложений (FileMon и ProcessMonitor).

Причина в том, что EasyHook внутренне использует:

RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(TRemoteObject),
                ChannelName,
                InObjectMode);

Этот удаленный вызов позволяет клиентам вызывать ваш (серверный) интерфейс, но сам сервер (вы, приложение) не может вызвать его.

Решение

Вместо этого используйте:

// Get the instance by simply calling `new RemotingInterface()` beforehand somewhere
RemotingServices.Marshal(instanceOfYourRemotingInterfaceHere, ChannelName);

Я добавил перегрузку в EasyHooks RemoteHook.IpcCreateServer (), чтобы принять мой новый "путь" делать .NET удаленного взаимодействия.

Это'Ужасно, но это работает:

Код

Замените весь метод IpcCreateServer (от фигурной скобки до фигурной скобки) следующим кодом. Здесь показаны два метода. Одним из них является более детальная перегрузка. Второй это "оригинал» метод, вызывающий нашу перегрузку.

public static IpcServerChannel IpcCreateServer<tremoteobject>(
        ref String RefChannelName,
        WellKnownObjectMode InObjectMode,
        TRemoteObject ipcInterface, String ipcUri, bool useNewMethod,
        params WellKnownSidType[] InAllowedClientSIDs) where TRemoteObject : MarshalByRefObject
    {
        String ChannelName = RefChannelName ?? GenerateName();

        ///////////////////////////////////////////////////////////////////
        // create security descriptor for IpcChannel...
        System.Collections.IDictionary Properties = new System.Collections.Hashtable();

        Properties["name"] = ChannelName;
        Properties["portName"] = ChannelName;

        DiscretionaryAcl DACL = new DiscretionaryAcl(false, false, 1);

        if (InAllowedClientSIDs.Length == 0)
        {
            if (RefChannelName != null)
                throw new System.Security.HostProtectionException("If no random channel name is being used, you shall specify all allowed SIDs.");

            // allow access from all users... Channel is protected by random path name!
            DACL.AddAccess(
                AccessControlType.Allow,
                new SecurityIdentifier(
                    WellKnownSidType.WorldSid,
                    null),
                -1,
                InheritanceFlags.None,
                PropagationFlags.None);
        }
        else
        {
            for (int i = 0; i < InAllowedClientSIDs.Length; i++)
            {
                DACL.AddAccess(
                    AccessControlType.Allow,
                    new SecurityIdentifier(
                        InAllowedClientSIDs[i],
                        null),
                    -1,
                    InheritanceFlags.None,
                    PropagationFlags.None);
            }
        }

        CommonSecurityDescriptor SecDescr = new CommonSecurityDescriptor(false, false,
            ControlFlags.GroupDefaulted |
            ControlFlags.OwnerDefaulted |
            ControlFlags.DiscretionaryAclPresent,
            null, null, null,
            DACL);

        //////////////////////////////////////////////////////////
        // create IpcChannel...
        BinaryServerFormatterSinkProvider BinaryProv = new BinaryServerFormatterSinkProvider();
        BinaryProv.TypeFilterLevel = TypeFilterLevel.Full;

        IpcServerChannel Result = new IpcServerChannel(Properties, BinaryProv, SecDescr);

        if (!useNewMethod)
        {
            ChannelServices.RegisterChannel(Result, false);

            RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(TRemoteObject),
                ChannelName,
                InObjectMode);
        }
        else
        {
            ChannelServices.RegisterChannel(Result, false);

            ObjRef refGreeter = RemotingServices.Marshal(ipcInterface, ipcUri);
        }

        RefChannelName = ChannelName;

        return Result;
    }

    /// <summary>
    /// Creates a globally reachable, managed IPC-Port.
    /// </summary>
    /// <remarks>
    /// Because it is something tricky to get a port working for any constellation of
    /// target processes, I decided to write a proper wrapper method. Just keep the returned
    /// <see cref="IpcChannel"> alive, by adding it to a global list or static variable,
    /// as long as you want to have the IPC port open.
    /// </see></remarks>
    /// <typeparam name="TRemoteObject">
    /// A class derived from <see cref="MarshalByRefObject"> which provides the
    /// method implementations this server should expose.
    /// </see></typeparam>
    /// <param name="InObjectMode">
    /// <see cref="WellKnownObjectMode.SingleCall"> if you want to handle each call in an new
    /// object instance, <see cref="WellKnownObjectMode.Singleton"> otherwise. The latter will implicitly
    /// allow you to use "static" remote variables.
    /// 
    /// <param name="RefChannelName">
    /// Either <c>null</c> to let the method generate a random channel name to be passed to 
    /// <see cref="IpcConnectClient{TRemoteObject}"> or a predefined one. If you pass a value unequal to 
    /// <c>null</c>, you shall also specify all SIDs that are allowed to connect to your channel!
    /// 
    /// <param name="InAllowedClientSIDs">
    /// If no SID is specified, all authenticated users will be allowed to access the server
    /// channel by default. You must specify an SID if <paramref name="RefChannelName"> is unequal to <c>null</c>.
    /// 
    /// <returns>
    /// An <see cref="IpcChannel"> that shall be keept alive until the server is not needed anymore.
    /// </see></returns>
    /// <exception cref="System.Security.HostProtectionException">
    /// If a predefined channel name is being used, you are required to specify a list of well known SIDs
    /// which are allowed to access the newly created server.
    /// </exception>
    /// <exception cref="RemotingException">
    /// The given channel name is already in use.
    /// </exception>
    public static IpcServerChannel IpcCreateServer<tremoteobject>(
        ref String RefChannelName,
        WellKnownObjectMode InObjectMode,
        params WellKnownSidType[] InAllowedClientSIDs) where TRemoteObject : MarshalByRefObject
    {
        return IpcCreateServer<tremoteobject>(ref RefChannelName, InObjectMode, null, null, false, InAllowedClientSIDs);
    }
</tremoteobject></tremoteobject></paramref></see></see></see></tremoteobject>

Тот'сидеть. Тот'Все, что вам нужно изменить. Ты ненужно изменить IpcCreateClient ().

Использование кода

Вот'Как бы вы использовали новый перегруженный метод:

Скажи у тебя есть

public class IpcInterface : MarshalByRefObject { /* ... */ }

как ваш общий интерфейс удаленного взаимодействия.

Создайте его новый экземпляр и сохраните его ссылку. Вы'Я буду использовать это для общения с вашим клиентом.

var myIpcInterface = new IpcInterface(); // Keep this reference to communicate!

Вот'Как бы вы создали этот удаленный канал?до:

        ipcServer = RemoteHooking.IpcCreateServer<ipcinterface>(ref IpcChannelName, WellKnownObjectMode.Singleton, WellKnownSidType.WorldSid);
</ipcinterface>

Вот'как бы вы создали этот удаленный каналсейчас:

        ipcServer = RemoteHooking.IpcCreateServer<ipcinterface>(ref IpcChannelName, WellKnownObjectMode.Singleton, myIpcInterface, IpcChannelName, true, WellKnownSidType.WorldSid);
</ipcinterface>

Дон»не забудьте ...

Я получил это решение отэто сообщение StackOverflow, Пожалуйста, не забудьте сделать, как он говорит, и переопределить InitializeLifetimeService, чтобы вернуть ноль:

public override object InitializeLifetimeService()
{
    // Live "forever"
    return null;
}

Я думаю, что это должно удержать клиента от потери интерфейса удаленного взаимодействия.

Пользы

Теперь вместо того, чтобы принудительно помещать файл интерфейса удаленного взаимодействия в тот же каталог, в котором находится проект внедрения, вы можете создать библиотеку специально для вашего файла интерфейса.

Это решение могло быть общеизвестным для тех, кто имел опыт работы с удаленным взаимодействием .NET, но я ничего не знаю об этом (возможно, в этом посте неправильно использовалось слово interface)

Ваш ответ на вопрос