Привет, думаю каждый знает утилиту proxychains, но не все могут понимать, как она работает под капотом, как её правильно пользоваться и почему не всегда в паре с ней работает nmap (и не только он).
Итак, Proxychains.
Утилита написана на C и давно не обновлялась. Сейчас используется её форк proxychains4 (или proxychains-ng), который мы и подразумеваем, опуская версию.
С её помощью можно запускать исполняемые файлы, трафик в которых будет перенаправлен через заданный прокси. Стандартный пример - пивотинг во внутреннюю сеть, в которой находится наш socks-прокси. Однако, её гибкий функционал также позволяет создавать и рандомизировать при каждом соединении цепочки прокси-серверов (наподобие сети TOR), для чего она, собственно, и создавалась.
Работает она, используя под капотом хуки API-функций. Да, как антивирусы и EDR. При вызове функции из glibc, например, “connect”, её управление перехватывается. В первом же абзаце README файла говориться, что данный способ буквально является взломом и может не всегда работать корректно.
Проведем в лабораторных условиях эксперимент с и без использования proxychains.
Поставим слушать tcp порт: echo hello | nc -lvnp 4444 и посмотрим на вывод strace:
# Подключаемся к серверу
kali$ strace -f -e network nc 127.0.0.1 4444
strace: Symbol `_UPT_accessors' has different size in shared object, consider re-linking
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(3, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
# сообщение от сервера
hello
^Cstrace: Process 13556 detached
kali$
Далее, чтобы не использовать сторонние прокси-сервера, будем использовать магию 127.0.0.1. Не все обращают на это внимание, но к виртуальному loopback-интерфейсу привязана целая сеть 127.0.0.0/8. подключимся к себе же по ssh и создадим socks-прокси:
# обратите внимание на адрес созданного сетевого сокета 127.13.37.1
kali$ ssh [email protected] -D 127.13.37.1:1080
Поставим этот прокси в конфиге proxychain:
socks5 127.13.37.1 1080
Смотрим на вывод strace и ищем изменения:
kali$ strace -f -e network proxychains -q nc 127.0.0.1 4444
strace: Symbol `_UPT_accessors' has different size in shared object, consider re-linking
strace: Process 13857 attached
# "= 3" изменилось на "= 7". Данное значение обозначает номер дескриптора. Все остальное одинаковое
[pid 13856] socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 7
[pid 13856] connect(7, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
[pid 13856] socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 7
[pid 13856] connect(7, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
[pid 13856] socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 7
[pid 13856] setsockopt(7, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
[pid 13856] setsockopt(7, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
# А вот тут идет магия proxychains. она перехватывает socket и connect и создаёт свой сокет на socks-прокси сервер
[pid 13856] getsockopt(7, SOL_SOCKET, SO_TYPE, [1], [4]) = 0
[pid 13856] socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 8
# И далее она вызывает свой собственный connect
[pid 13856] connect(8, {sa_family=AF_INET, sin_port=htons(1080), sin_addr=inet_addr("127.13.37.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
# А также и getsocksopt, для записи вывода в дескриптор stdout
[pid 13856] getsockopt(8, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
hello
^Cstrace: Process 13856 detached
strace: Process 13857 detached
kali$
Как мы видим, сравнивая эти 2 вывода, функция connect заменена на новую последовательность вызовов сетевых функций для перенаправления трафика.
Теперь попробуем с UDP-пакетами
Без proxychains