Для начала давайте внимательно посмотрим на прототип функции RpcServerRegisterIf2
Первым параметром передается RPC_IF_HANDLE, который описан в RpcDce.h как
typedef void __RPC_FAR * RPC_IF_HANDLE;
Что есс-но неправда. Лучше всего смотреть в серверную часть, сгеренерированную midl - там эта структура описана уже как RPC_SERVER_INTERFACE. Ее определение, взятое из RpcDceP.h:
typedef struct _RPC_SERVER_INTERFACE
{
unsigned int Length;
RPC_SYNTAX_IDENTIFIER InterfaceId;
RPC_SYNTAX_IDENTIFIER TransferSyntax;
PRPC_DISPATCH_TABLE DispatchTable;
unsigned int RpcProtseqEndpointCount;
PRPC_PROTSEQ_ENDPOINT RpcProtseqEndpoint;
RPC_MGR_EPV __RPC_FAR *DefaultManagerEpv;
void const __RPC_FAR *InterpreterInfo;
unsigned int Flags ;
} RPC_SERVER_INTERFACE, __RPC_FAR * PRPC_SERVER_INTERFACE;
RPC_SYNTAX_IDENTIFIER описан в том же файле как
typedef struct _RPC_SYNTAX_IDENTIFIER {
GUID SyntaxGUID;
RPC_VERSION SyntaxVersion;
} RPC_SYNTAX_IDENTIFIER, __RPC_FAR * PRPC_SYNTAX_IDENTIFIER;
InterfaceId.SyntaxGUID - это наш UUID, который можно найти например алгоритмом Бойера-Мура
Длина структуры под win32 0x44 байта, под win64 0x60 байт
Итак у нас есть RPC_SERVER_INTERFACE. Из поля DispatchTable.DispatchTableCount можно узнать количество методов в интерфейсе, но в DispatchTable.DispatchTable хранятся не сами адреса функций, а лишь Ndr-переходники
Нужную нам таблицу можно получить из поля RPC_SERVER_INTERFACE.InterpreterInfo - оно указывает на структуру MIDL_SERVER_INFO. Ее описание, взято из файла RpcNdr.h:
typedef struct _MIDL_SERVER_INFO_
{
PMIDL_STUB_DESC pStubDesc;
const SERVER_ROUTINE * DispatchTable;
PFORMAT_STRING ProcString;
const unsigned short * FmtStringOffset;
const STUB_THUNK * ThunkTable;
PRPC_SYNTAX_IDENTIFIER pTransferSyntax;
ULONG_PTR nCount;
PMIDL_SYNTAX_INFO pSyntaxInfo;
} MIDL_SERVER_INFO, *PMIDL_SERVER_INFO;
Вот ее поле DispatchTable - это уже именно то что нужно
Итого алгоритм примерно такой - находим по RPC interface UUID cтруктуру RPC_SERVER_INTERFACE, проверяем ее длину, из RPC_SERVER_INTERFACE.DispatchTable.DispatchTableCount получаем число методов, из RPC_SERVER_INTERFACE.InterpreterInfo.DispatchTable - указатель на таблицу с адресами методов. Просто и надежно как топор
А как получить RPC_IF_HANDLE по UUID-у для _уже_ запущенного RPC сервера (имея доступ к его хост-процессу)? Относительно простого и документированного способа это сделать я так и не нашел.
ОтветитьУдалитьнаверное исключительно из всяких недокументированных структур rpcrt4.dll
ОтветитьУдалитьНо у предложенного способа угона и нет такой задачи - я обычно знаю имя модуля, в которой лежит RPC_IF_HANDLE - мне нужно таблицу найти с обработчиками, а дальше либо проверить что ничего не пропатчено (а для этого все равно таблицу нужно с файла модуля с диска парзить), либо угнать самому
Да, есть такой способ.
ОтветитьУдалитьЯ им пользуюсь вот здесь crfilter.com.
Однако, хотя способ будет работать по бегущему процессу, делать это не стоит, чревато.
Лично я все равно патчу До взлета.
Есть правда проблемы с патчами системых процессов на 8 ядре, Майкрософт там новую защиту довесила и даже не обьявила.:( Но это уже другая проблема.
do you mean control flow guard ?
ОтветитьУдалитьТам три этапа:
ОтветитьУдалить1. Инструментирую процесс
2. Хукирую один АПИ (возможно через RpcServerRegisterIf2 тоже получится, я не проверял).
3. Добираюсь до DispatchTable и стабирую ее.
Защиту Майкрософта я давно преодолел - работает на 10-м кермнеле тоже. Смотри там же, последний лист: http://crfilter.com/anti-malware-protection.html.
Хоокирую services.exe в том числе.
Если хочешь спросить, в личку, там есть адрес.