Algumas novidades sobre as pesquisas no Sagemcom Router F@ST 1704 (“F1704″): novas informações, como enviar e executar aplicativos no router e notas gerais.
Depois que a Sagemcom (“SC”) liberou os fontes e o toolchain, animei a olhar o F1704 novamente. É bem mais fácil trabalhar com o material correto. Tirei um tempo para ver do que se tratava e conseguimos resultados razoáveis! Se pretende fazer tweaks neste router, ele tem potencial (ou terá, espero!). Bem, vamos ver o que conseguimos com o tempo. Neste momento, meu F1704 está com um kernel custom e alguns utilitários rodando! Note que ele não é meu modem/router principal, por isso não posso dizer se ele é “bom” ou não. É só hacking for the heck of it!
O pacote liberado pela SC contém o fonte do kernel, de algumas bibliotecas e aplicativos sob GPL, e fontes públicos da Broadcom (“BCM”). Como ferramentas, veio o toolchain GCC para MIPS – usando a uClibc -, e alguns utilitários de compressão e CRC de imagens. Obviamente não é o pacote completo, existe uma quantidade considerável de código proprietário de ambas SC e BCM que não são disponibilizadas, por isso somos obrigados a conviver com binários e, muito provavelmente, com esta versão de kernel, para evitar dor de cabeça com os módulos que não temos os fontes.
Apesar do pacote dar potencial à modificações no F1704, ele não permite gerar uma imagem final para flash via interface web ou executar um kernel construído por você. Wait, what!? Vou explicar mais à frente. Vamos ver o que pode ser feito no router por agora.
Antes de partir para modificações e novos aplicativos, notei que existem algumas ferramentas interessantes já disponíveis no router. Se já andou vasculhando os arquivos no sistema interno, isso não é novidade e pode pular para o próximo tópico. Caso não, veja, em especial, os comandos que terminam com “ctl”: são aplicativos que permitem controlar diversos parâmetros do router:
<td>
<div class="text codecolorer">
# ls /bin/*ctl<br /> /bin/adslctl /bin/ethctl /bin/xdslctl<br /> /bin/brctl /bin/wlctl /bin/xtmctl<br /> # ls /sbin/*ctl<br /> /sbin/ethctl /sbin/smuxctl
</div>
</td>
</tr>
Por exemplo o wlctl, que têm muitos parâmetros bacanas para controlar a interface wifi, que permitem desde alterar a potência de TX, a adicionar IEs customs nos beacons de sua rede com alguma mensagem oculta. 😀
Enviando e executando aplicativos no router
Enviando arquivos ao router
Primeiramente, você precisa ter acesso ao shell do router. Acesse via telnet e faça login com as credenciais. Se não alterou a padrão, é user “admin”, pass “gvt12345″. Assim que logar, receberá um shell simplificado com comandos dedicados à operação do router. Queremos o BusyBox. Digite “sh” para se libertar! Onde ver “192.168.1.105”, substitua pelo IP de seu router.
<td>
<div class="text codecolorer">
tripleoxygen@stratosphere:~$ telnet 192.168.1.105<br /> Trying 192.168.1.105...<br /> Connected to 192.168.1.105.<br /> Escape character is '^]'.<br /> BCM96338 xDSL Router<br /> Login: admin<br /> Password:<br /> > sh
</div>
</td>
</tr>
BusyBox v1.00 (2011.04.01-10:08+0000) Built-in shell (msh)
Enter ‘help’ for a list of built-in commands.
Geralmente, routers são bem “trancados” e oferecem poucos comandos no shell, restringindo o usuários apenas aos recursos de configuração. Veja como o BusyBox foi compilado com poucos applets:
<td>
<div class="text codecolorer">
# help<br /> Built-in commands:<br /> -------------------<br /> . : break cd continue eval exec exit export help login newgrp<br /> read readonly set shift times trap umask wait [ busybox cat chmod<br /> cp date df dmesg echo expr false ftpget ifconfig init insmod<br /> kill killall klogd linuxrc ln logger logread ls mkdir mount msh<br /> ping ping6 ps pwd reboot rm rmmod route sendarp sh sleep smuxctl<br /> sysinfo syslogd test top true tty umount vconfig
</div>
</td>
</tr>
Note que não temos nem mesmo “mv”! Desta maneira, se quiséssemos rodar algum aplicativo no router, como faríamos para colocar algo lá dentro, já que estamos em um ambiente restrito como esse? Não existe nenhum meio óbvio (não que eu tenha imaginado! haha). E não, o ftpget visto ali não funciona, foi comentado no fonte do BusyBox pela SC. 😉 Teríamos que bolar uma maneira de enviar estes dados usando este canal que temos, o shell via telnet. Mas estamos restritos a comandos de texto, correto? E para binários?
Lembre-se que podemos usar o comando echo com a opção -e e sequências escapadas para representar qualquer byte. Exemplo:
<td>
<div class="text codecolorer">
# echo -e '\x54\x65\x73\x74\x65'<br /> Teste
</div>
</td>
</tr>
Melhor ainda: redirecionamos a saída para um arquivo, e ao invés de texto, bytes representando algum dado binário:
<td>
<div class="text codecolorer">
# echo -e '\x00\xF0\xFF\x7E\x00' >> /var/my_app<br /> # chmod +x /var/my_app
</div>
</td>
</tr>
Temos então, uma maneira de enviar quaisquer dados ao router. Obviamente, algo deve automatizar este processo, lendo o arquivo que queira enviar, convertendo em sequências de texto como mostrado acima e enviando ao router. Use o sendbin.py para isso. Execute-o sem parâmetros na sua máquina para saber como usá-lo. Creio ter visto algo parecido em algum lugar, caso alguém saiba, diga onde.
A ideia agora, é enviar algum aplicativo que facilite o envio de outros e de maneira mais rápida. Assim, compilei o netcat para este propósito. Já temos como executar nossos aplicativos no router! Resumindo o processo:
- Envie o netcat com o sendbin (não esteja logado via telnet no router, ou o sendbin falhará):
<td>
<div class="text codecolorer">
./sendbin.py 192.168.1.105 admin gvt12345 netcat
</div>
</td>
</tr>
</table>
- Faça login no router via telnet e execute a partir do shell do BusyBox:
<td>
<div class="text codecolorer">
/var/netcat -l -p 9999 > /var/my_app
</div>
</td>
</tr>
</table>
<td>
<div class="text codecolorer">
cat my_app | nc -q 30 192.168.1.105 9999
</div>
</td>
</tr>
</table>
<td>
<div class="text codecolorer">
chmod +x /var/my_app<br /> /var/my_app
</div>
</td>
</tr>
</table>
Instalando o pacote fornecido e compilando aplicativos
Agora que temos certeza que podemos “fazer alguma coisa” no router, vamos ao ambiente de desenvolvimento.
Já que a SC forneceu o toolchain, optei por utilizá-lo e assim “facilitar a vida”. Se ainda não o baixou, veja o link no final da página, ele acompanha o pacote. Aproveite para instalar todo o ambiente fornecido. Descompacte o pacote F@ST1704GVT_4.42_consumer_release.tar.gz, você terá 3 arquivos:
- o toolchain: uclibc-crosstools-gcc-4.2.3-3.tar.bz2
- os fontes: F@ST1704GVT_4.42_consumer.tar.gz
- script de instalação: consumer_install
Renomeie o pacote de fontes de F@ST1704GVT_4.42_consumer.tar.gz para bcm96338_consumer.tar.gz, ou o script não encontrará. Instale com:
<td>
<div class="text codecolorer">
$ ./consumer_install
</div>
</td>
</tr>
Os fontes serão instalados em /opt/bcm963xx_router e o toolchain em /opt/toolchains/uclibc-crosstools-gcc-4.2.3-3. Daqui, você já pode construir todo (*cough*cough*) o sistema do F1704. Tanto o kernel como o userspace estão nesta árvore e são compilados automaticamente caso você dê um make na raíz. Para construir tudo (kernel + user):
<td>
<div class="text codecolorer">
make PROFILE=F@ST1704GVT
</div>
</td>
</tr>
Mantenha o perfil em todas as operações que fizer. Para compilar os realms separadamente, use as regras “kernel” ou “userspace” para o make. A saída da compilação ficará em targets/F@ST1704GVT. Note que o kernel não é copiado, e deve ser pego de kernel/linux/vmlinux. Obviamente ele ainda não está no formato adequado para o router. Informações sobre kernelspace no F1704 ficam para um próximo post.
E agora, como usar tudo isso para compilar meus apps? Podemos apenas usar o toolchain e compilar manualmente (ou configurá-lo no Buildroot, por exemplo, que é como estou fazendo), ou adicioná-lo na árvore oficial, para ele seja compilado com todo o resto do sistema.
Vou abordar brevemente como adicioná-lo na árvore oficial. A vantagem é que temos acesso às bibliotecas oferecidas pela SC e BCM, que oferecem funções específicas para o F1704 (cms_boardctl, cms_util, …).
Copie a pasta com o fonte de seu app ou outro app qualquer que pretende compilar (o app deve ter port para MIPS) para:
<td>
<div class="text codecolorer">
/opt/bcm963xx_router/userspace/public/apps
</div>
</td>
</tr>
Note que já existe alguns apps. Após copiado, você terá que adicionar seu novo aplicativo ao Makefile do sistema, para que ele possa construí-lo no próximo make. Abra o Makefile raíz da pasta apps e adicione o seu. Basta observar como os existentes foram adicionados e incluir o novo.
Para o Makefile específico (i.e. usado para construir o app), caso necessário, copie de algum aplicativo já na árvore e adapte-o. Depois de adicionado, volte à raiz do do sistema e:
<td>
<div class="text codecolorer">
$ cd /opt/bcm963xx_router<br /> $ make PROFILE=F@ST1704GVT userspace
</div>
</td>
</tr>
Dependendo das configurações de seu Makefile, o binário poderá ser copiado para o staging do rootfs em targets/F@ST1704GVT/fs.install. Se não for este o caso, ele estará na pasta do fonte, de acordo com as regras originais do Makefile. Agora, envie o binário ao router e execute!
Observação: a biblioteca do uClibc presente no router não é exatamente a mesma contida no toolchain. A versão do router está extremamente stripped para reduzir o tamanho do binário, por isso, algumas funções não utilizadas foram removidas. Neste caso, pode acontecer de sua aplicação não encontrar algum símbolo ou outro quando executado no router. Implemente esta função você mesmo, faça link estático ou copie a biblioteca compartilhada (libuClibc-0.9.29.so) do toolchain junto de seu app para o router (certifique-se de criar o link simbólico libc.so.0 que aponta para ela). Como exemplo de símbolos que não existem: strlcpy e ptrace.
Pesquisas futuras
Como foi dito, atualmente não é possível gerar imagens de firmware que podem ser usadas para atualizar o router e tornar permanentes suas modificações.
Já sei o porquê e estou trabalhando nisto. Adiantando: a Sagemcom não usa simples CRC32 para validar o cabeçalho das imagens (“tags”). Ela usa sim, para validar o rootfs e o kernel, mas o cabeçalho não. O interessante é o fato que nos fontes fornecidos, está claro que este checksum é CRC32 também, mas não é caso na “vida real”. Na verdade, o CRC32 que a Broadcom usa é um CRC32 com todos os bits invertidos, mas pelo menos isso é documentado. Enfim, a Sagemcom fornece os fontes mas não quer que os usuários mexam no router. Sujo? Sim!
Algumas notas adicionais que deixo aqui:
- As imagens de firmware existentes não incluem o CFE (bootloader). Isso torna o processo de update mais seguro, já que não há chances de acidentalmente corrompê-lo ao atualizar. Mesmo que o kernel ou o rootfs falhe, você terá o CFE via porta serial para resgatar o router. Parece que o CFE também tem uma interface web para isso, o que seria melhor ainda.
- Fiz um dump completo da flash (4 MB) incluindo todas as partições e documentei o layout da flash. Com o kernel atual, não se pode ler regiões além das permitidas pelo código responsável no kernel (e.g. NVRAM, Scratchpad). Para resolver isso, modifiquei o kernel adicionando um novo parâmetro no IOCTL que controla alguns recursos a nível de “placa” (/dev/brcmboard) que permite ler qualquer endereço da flash.
Assim que tiver tempo, escrevo um novo post com novas informações. Vejam o file vault, lá tem algumas coisas úteis para quem quiser mexer no F1704. Como exemplo, deixei o binário do tcpdump pronto para uso.