Как стать автором
Обновить

Как я учил войс чат дискорда работать через прокси с помощью перехвата системных вызовов и DLL Hijacking

Уровень сложностиСредний
Время на прочтение16 мин
Количество просмотров20K
Всего голосов 25: ↑25 и ↓0+32
Комментарии38

Комментарии 38

ЗакрепленныеЗакреплённые комментарии

Дополню, пожалуй... Подход использованный в ProxiFyre (с редиректом трафика на прозрачный локальный прокси и дальнейшей передачей через SOCKS5) довольно старый, но достаточно практичный. Ровно так же и на том же драйвере уже много лет работает сетевая фильтрация ZScaler, разве что вместо SOCKS5 трафик перенаправляется через HTTP-proxy.
Есть еще вариант завернуть TCP соединение на redirect layer WFP (задержка на таком редиректе меньше, чем спуститься до NDIS и вернуться обратно), но, к сожалению, для UDP этот уровень работает не так как хотелось бы.
Если кому-то интересно сделать полноценное коммерческое решение на основе ProxiFyre и завернуть все в инсталлятор, я не возражаю. Если нет возможности лицензировать драйвер, то за "долю малую" сделаю специализоварованную сборку и помогу чем смогу, в оригинальном ProxiFyre есть что соптимизировать. Заниматься этим направлением самостоятельно у меня, к сожалению, сейчас нет времени.

Из-за этого постоянно приходится включать режим TUN/VPN, который заворачивает в туннель много лишнего.

Использовал Nekobox, где в Tun Settings включил Whitelist Mode и прописал discord и браузеры в Proxy Process Name.

Чем такой вариант хуже? В этом случае он всё равно все приложения заворачивает в TUN?
У меня с такими настройками была проблема с онлайн игрой Deadlock, которая временами лагала и разрывала соединения. (В итоге перешел на sing-box с почти теми же настройками и пока проблем не наблюдаю)

Да, sing-box на бумаге имеет возможность заворачивать отдельные процессы, но его реализация TUN достаточно слабая и костыльная.

Во первых, это заметно снижает сетевую производительность и увеличивает задержки. Вы, возможно, могли замечать, что даже если вы не завернули процесс игры в туннель, у вас все равно, скорее всего, вырастет пинг.

Во вторых, sing-box сильно вмешивается в сетевой трафик, что можешь приводить к проблемам с кучей протоколов, отличных от TCP и UDP. Я видел много жалоб на проблемы с, к примеру, сетевыми дисками.

Хорошим примером странного вмешательства в трафик является ICMP - попробуйте попингать любой (даже заведомо недоступный) IP адрес - вы всегда получите ICMP "ответ" с задержкой <1ms. Его зачем-то встроит sing-box.

В третьих, TUN режим оперирует не доменными имена и HTTP запросами как прокси, а только IP адресами, что в значительной степени ломает маршрутизацию на основе правил, базирующихся на доменных именах. Да, можно включить TUN + прокси, но не все об этом знают и помнят.

Ну и так далее... Так что, учитывая количество проблем с этим, хотелось бы использовать этот TUN режим пореже.

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

Нет, к сожалению, нельзя. В Windows есть механизм, называемый KnownDLLs

По сути это список основных системных библиотек, которые всегда будут загружаться из System32.

ws_32.dll туда тоже входит, можете посмотреть в реестре по пути HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs

Сделать бы еще универсальное решение с ддлкой - "wsock32.dll" (x86/x64), дав "проброс функций" на оригинальную дллку. Такой библиотеки крайне не хватает.

К сожалению так не получится, в win10/11 wsock32.dll это просто заглушка, которая никуда фактически не загружается.

Там ws_32 судя по коду поддерживает несколько "провайдеров", но лично у меня все вызовы отправляеются в mswsock.dll, в функции вроде WSPConnect, WSPSendTo и так далее.

Но и тут засада - эти функции не экспортируются, вместо этого экспортируется только функция WSPStartup, которая чертвертым аргументом заполняет у вызывающего тот самый массив "провайдеров" и передает таблицу вызовов (аргумент WSPUPCALLTABLE *UpcallTable)

Так что это не вариант - чуть ОС обновилось, добавилась 1 новая функция в эту таблицу и все сломалось...

Ну а про прокси dll для ws_32 смотрите выше.

но, к сожалению, голосовой чат дискорда не поддерживает работу через прокси

А можно уточнить почему? Разве через какой-нибудь proxifyre не будет работать? Я сам не попробовал потому что не нашёл socks5 прокси сервера с внятной поддержкой UDP, но по идее в чем тут проблема может то быть?

Так я расписал в чем проблема Proxifier. Но вообще socks5 это в том числе все китайские протоколы типа vless

Наверное речь про это: https://github.com/wiresock/proxifyre (универсальное приложение для проксирования выборочных процессов через socks5).

А популярный proxifier не работает с UDP.

Есть еще вот такое: https://github.com/nefarius/socksifier

И вот такое: https://sourceforge.net/projects/sockscap64/

Касательно proxifyre - это закрытое решение. Работает через драйвер (закрытый). Так что я описал почему для меня это был не вариант.

Но вообще решение пусть и закрытое, но я обсуждал в свое время покупку прав на использование драйвера с его автором - Вадимом Смирновым. Для личного использования дороговато, но если рассматривать с точки зрения разработки своего клиента для продажи, то он копейки просит.

Так что ничего плохого про proxifyre сказать не могу, просто хотелось полностью открытое решение.

Что касается socksifier - он гарантированно не будет работать с дискордом и хромиумом из-за слишком наивной и ленивой релизации. Он крашет процесс на том же этапе, где я в своей статье начал первые тесты.

sockscap64 - это древнее полностью закрытое решение, которое почти наверняка не заработает в современной ОС. Мне, если честно, даже немного стремно его ставить.

Если я не ошибаюсь, то автор Windows Packet Filter и proxifyre есть на хабре - @SerpentFly

Мало ли кому-то будет интересно сделать универсальное решение.

Дополню, пожалуй... Подход использованный в ProxiFyre (с редиректом трафика на прозрачный локальный прокси и дальнейшей передачей через SOCKS5) довольно старый, но достаточно практичный. Ровно так же и на том же драйвере уже много лет работает сетевая фильтрация ZScaler, разве что вместо SOCKS5 трафик перенаправляется через HTTP-proxy.
Есть еще вариант завернуть TCP соединение на redirect layer WFP (задержка на таком редиректе меньше, чем спуститься до NDIS и вернуться обратно), но, к сожалению, для UDP этот уровень работает не так как хотелось бы.
Если кому-то интересно сделать полноценное коммерческое решение на основе ProxiFyre и завернуть все в инсталлятор, я не возражаю. Если нет возможности лицензировать драйвер, то за "долю малую" сделаю специализоварованную сборку и помогу чем смогу, в оригинальном ProxiFyre есть что соптимизировать. Заниматься этим направлением самостоятельно у меня, к сожалению, сейчас нет времени.

Есть еще альтернативное решение от hdrover: https://github.com/hdrover/discord-drover
Правда тут подходят только https прокси. А голос идет без прокси (соответственно меньше лаг), но работает через небольшой хак. И вмешательства в процесс минимальные.

Странно, в линуксе дискорд нормально работает, если запустить так:
discord --proxy-server=socks5://proxy-server-adr:port

В windows это не работает. Первый процесс, который проверяет наличие новых версий, не использует прокси из командной строки. И пропустить этот шаг нельзя.

Увы. Но скоро и habr заблочат. Этот один из последних ресурсов, который предоставляет такую информацию.

По той же причине, и github заблокируют.

Я использую конфиг wg, у которого в AllowedIPs прописаны подсети дискорда коих списками куча на гитхабе.

Wireguard почти ни у кого в России не работает.

Есть костыльные варианты вроде AmneziaWG, но его реализация не предполагает серьезную устойчивость к блокировкам. Захотят - заблокируют очень быстро.

трафик же не весь идет, кому интересно за этим куском в ркн следить?)
да и можно через shadowsocks завернуть при желании.
по поводу что в России не работает ни у кого - странный вывод.

трафик же не весь идет, кому интересно за этим куском в ркн следить?)

Что значит "в ркн следить"? Протокол блокируется на трансграничном ТСПУ автоматически, разом и почти у всех.

да и можно через shadowsocks завернуть при желании.

Нельзя, shadowsocks тоже легко заблокировать (и уже блокируется)

по поводу что в России не работает ни у кого - странный вывод.

Это не странный вывод, а объективная реальность. Практически у всех на ТСПУ блокируется трансграничный wireguard. Почитайте, хотя бы, тут

Объективно сейчас надежными являются только протоколы, которые очень хорошо маскируются под что-то совершенно легальное, вроде https. Поэтому сейчас большая часть людей использует решения, которые применяются для обхода китайского GFW, к примеру VLESS + REALITY.

Очевидно, что ркн до gfw очень далеко, а значит у нас есть много времени пока они что-то не придумают.

понятно, похоже для меня блокировка - дело времени

Воспользовался вашим способом проксирования discord. Но есть проблема. У меня все отлично работает и инсталятор, и вариант установки вручную. У друга не работает ни тот, ни другой способ. Инсталятор просто не запускается(с включенным и нет фильтром смарт скрин, а также с прамави администратора), а при установке вручную Discord не видит прокси. Делали все одинаково на 10 винде. Проксирую на локальный прокси запущенный с некобокса. Есть предположения в чем может быть проблема?

Если еще актуально, пусть друг попробует поставить фреймворк .NET 8 и 9 версий

Имеется ли авторизация для прокси? Не очень хочется открытым держать...

Да, конечно, через логин/пароль. Инсталлятор спросит у вас, но если устанавливаете руками, то надо к инструкции выше еще 2 строчки написать

SOCKS5_PROXY_LOGIN=login
SOCKS5_PROXY_PASSWORD=password

Больше информации тут

Проверил. Сходу не работает. На этапе dll hijack что-то пошло не так, наверное потому что у меня Discord.exe 32-битный и подгружает DWrite.dll из C:\Windows\SysWOW64, а ваша DWrite.dll PE64+ executable.
По-хорошему должна быть поддержка x86 и x86_64 архитектур бинарников.
А кстати почему перехватываете DWrite.dll а не, например, dbghelp.dll ?
Для того же TeamSpeak я реализовывал hijack и хук функций именно через dbghelp.dll как наиболее универсальный вариант.

Не поделитесь решением для Teamspeak?

Пересоберите под 32 бит или я могу пересобрать, если ещё актуально

Это же Си, тут просто.

Думаю, выбор длл не имеет большого значения.

Это не просто Си. Автор использовал MASM в проекте, для ускорения описания функции перехватываемой хуком. Вы просто так не соберёте его под 32 бит.
Только если чуть-чуть поправить - и уже собрал всё что мне нужно.
Ещё забавно, вот такой ньюанс.
Описание оригинальной функции, подвергаемой хуку из MSDN:
HRESULT DWriteCreateFactory(
[in] DWRITE_FACTORY_TYPE factoryType,
[in] REFIID iid,
[out] IUnknown **factory
);

При этом из той же MSDN: "In 64-bit MAPI, HRESULT is still a 32-bit value."
Автор же почему-то применяет описание экспортируемой функции qword, хотя с точки зрения соглашения вызова WINAPI это может быть не так критично, т.к. результат записывается в регистр eax (32-бит) - он же rax (64-бит), повлияет ли это на корректную передачу аргументов через стек и передачу результата из OrignalDWriteCreateFactory через этот регистр? Возможно нет. Но на всякий случай обращаю внимание на неточность.

А где там масм, в proxy.asm? Или где-то еще был ?
На 64 бит все значения возвращаются в RAX, просто в случае HRESULT это займет нижние 32 бита (EAX). Думаю, проблем не будет, HRESULT редко передают как параметр, разве что логировать успех/неуспех апи

у меня через ProxiFyre. Только иногда надо его в службах перезапускать, бывает не проксирует если ПК из спячки выходит

Приветствую!

Не планируете ли сделат аналогичный софт для Teamspeak?

Есть какие-нибудь подобные решения для линукса?

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

тоже заработало для VMESS, для VLESS не захотело

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации