Adaptando a correção do Cisco AnyConnect vpnagentd para o OSX

2

Estou tentando encontrar uma solução para permitir o tunelamento dividido com o cliente Cisco AnyConnect para o OSX. Descobri como isso está modificando o firewall e isso é possível corrigir. O problema é que o daemon vpnagentd mantém o seqüestro da tabela de roteamento.

Sasha Pachev propôs uma solução elegante para o Linux ( link ), mas estou tendo desafios para adaptá-lo ao OSX .

O hack.c escrito para o Linux faz referência a um linux / netlink.h , que não está presente no OSX. Eu acho que é onde o AF_NETLINK vem.

#include <sys/socket.h>
#include <linux/netlink.h>

int __ZN25CInterfaceRouteMonitorMac20routeCallbackHandlerEv()
{
  int fd=50;          // max fd to try
  char buf[8192];
  struct sockaddr_nl sa;
  socklen_t len = sizeof(sa);

  while (fd) {
     if (!getsockname(fd, (struct sockaddr *)&sa, &len)) {
        if (sa.nl_family == AF_NETLINK) {
           ssize_t n = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
        }
     }
     fd--;
  }
  return 0;
}

Não estou familiarizado com este idioma, por isso não sei onde procurar. Posso ver outras pessoas fazendo referência na pergunta original para adaptar isso ao OSX, mas não vejo os resultados publicados em nenhum lugar.

Alguém teve alguma sorte em adaptar este método ao OSX? Qualquer ajuda muito apreciada.

Depois que eu tiver esse aspecto funcionando, ficarei feliz em compartilhar a solução completa.

    
por James Miller 14.03.2016 / 14:23

2 respostas

1

(Eu escrevi a versão expandida desta função que drena os dados NETLINK, seguindo o impressionante trabalho de detetive de Sasha Pachev, encontrando que função interceptar. Fico feliz em ver que as pessoas acharam o código útil.)

Do outro segmento, vejo alguém usar "nm" para descobrir que existe um manipulador de retorno de chamada análogo para o OSX e você está tentando criar uma função adequada para substituí-lo. Eu entendo que o OSX não fornece uma interface NETLINK, então é muito improvável que a versão OSX do AnyConnect mantenha o controle sobre a tabela de roteamento da mesma maneira que o cliente Linux faz. Eu não sei qual mecanismo o OSX fornece para sinalizar para AnyConnect que uma mudança de roteamento aconteceu, mas como não é baseado em NETLINK, o código aqui para drenar a mensagem de netlink é inaplicável.

Ironicamente, o estilo de função stub original fornecido por Sasha provavelmente seria tudo o que você precisaria para impedir que ele substituísse suas rotas pelas suas próprias. Essa função parecia:

int __ZN25CInterfaceRouteMonitorMac20routeCallbackHandlerEv()
{
  return 0;
}

No linux, essa função original levou a um alto uso da cpu, porque o evento NETLINK que acionou a chamada para o manipulador de retorno de chamada nunca seria limpo por esse código do-nothing. o mesmo efeito pode acontecer para o cliente OSX, onde qualquer evento que dispara esta função não está sendo limpo também. Mas se esta função é a função manipuladora correta para interceptar, e você é capaz de fazer sua própria biblioteca para sobrescrever essa função, e conseguir que a biblioteca seja carregada em vez da biblioteca real, pelo menos você a impedirá de redefinir a tabela de roteamento a cada vez que você tenta mudar você mesmo. Se você chegar tão longe, sacrificar alguma CPU pode valer a pena.

Boa sorte!

    
por 15.04.2016 / 18:14
1

Acabei de encontrar este post. Pensei em compartilhar meus resultados.

Eu fiz esse truque no OSX. A solução dada por Rubio realmente funciona (e também resulta em 100% de CPU em um núcleo, infelizmente).

Eu não consegui enganar o carregador usando minha função, já que o OSX não usa o LD_PRELOAD e o DYLD_INSERT_LIBRARIES não estava funcionando para esse binário por algum motivo. Se alguém se deparar com esse problema, eu resolvi isso editando o assembly libvpnagentutilities.dylib original (um editor hexadecimal é seu melhor amigo aqui)

Substitua os primeiros 6 bytes da função pelas seguintes instruções para obter o mesmo efeito de "retorno 0" que o código C dado acima:

__ZN25CInterfaceRouteMonitorMac20routeCallbackHandlerEv:
0007add0        movl    $0x0, %eax  
0007add5        retl

No entanto, depois de mais um rastreamento de chamada de função, descobri uma maneira de fazer isso sem aumentar a utilização da CPU. Na verdade, é mais simples que a minha solução acima. Há outro símbolo que é delegado na verdade a tarefa de modificar a tabela de rotas chamada _ZN28CInterfaceRouteMonitorCommon20routeCallbackHandlerEv. Rastreando a pilha de chamadas dessa função, encontrei a função que ela chama para efetuar a mudança no deslocamento 67c06.

A solução? Ignore as alterações que listei anteriormente e, em vez disso, simplesmente substitua a instrução de chamada em 67c06 por nop's !!

Aqui está o antes:

00067c03        movl    %eax, (%esp) 
00067c06        calll   *0x8(%ecx)   
00067c09        addl    $0x4, %esp   

E aqui está a versão final:

00067c03        movl    %eax, (%esp)
00067c06        nop
00067c07        nop
00067c08        nop
00067c09        addl    $0x4, %esp

Isso deve ser tudo o que você muda. Substitua o original vpnagentutilities.dylib com esta versão modificada e desfrute de uma tabela de rotas sem babá. Ele ainda modificará a tabela durante a conexão inicial, mas você estará livre para alterá-la da maneira que achar melhor.

EFF VOCÊ ANYCONNECT!

    
por 03.02.2017 / 05:14