Revivendo uma câmera IP chinesa

Nesse post vamos ver como reviver uma câmera IP chinesa da Marca Besder comprada no aliexpress, que utiliza o chip da xiongmaitech (que inclusive me pareceu famosa pela falta de segurança em suas câmeras. Tem várias postagens pela internet falando das brechas de segurança nos equipamentos).

A câmera deixou de funcionar depois da tentativa de atualização do firmware a partir do aplicativo ICSee. A atualização travou e depois disso, não ligou mais. Não adiantava tentar o reset, nem nada.

Pesquisando na internet, descobri que esse tipo de câmera possui uma interface de comunicação serial, porém não facilmente acessível. A partir daí seria possível realizar alguns procedimentos para tentar reinstalar o firmware e reestabelecer o funcionamento normal da câmera.

Faça esse procedimento por sua conta e risco. Não é um processo simples e muita coisa pode dar errado.

Se você tem interesse em comprar uma câmera igual a essa, pode comprar no aliexpress, é mais barato do que comprar no mercado livre por exemplo, embora demore um pouco mais. A Besder, que é o vendedor onde comprei essa câmera até então é de confiança, todos os produtos que comprei com eles vieram certinho e o suporte é bom também. Se tiver interesse, abaixo coloquei alguns links com câmeras que já comprei e são boas. Algumas inclusive você pode rotacionar remotamente, segue o link da câmeras, é só clicar na câmera desejada:

 

Identificando os pinos UART (GND, TX, RX)

Primeiro de tudo é necessário identificar quais são os pinos UART na placa da câmera. Para isso segui alguns passos, conforme alguns posts que li, dá uma olhada mais abaixo nas referências para ver os links.

Em resumo, abri a câmera e procurei por uma seção de 4 pinos padrão que parececem ser os pinos que eu queria. No meu caso, estava relativamente fácil de identificar, uma vez que estava bem claro 4 pinos, sendo que um deles estava demarcado com um “1”.

Geralmente são 4 pinos, pois o VCC também eu acho que sempre está junto. O pino demarcado com o “1”, no meu caso é o VCC mesmo, com saída de 3.3v.

GND. Mas vamos lá, para descobrir isso, utilizei um multímetro e o primeiro pino que tentei descobrir foi o GND que teoricamente é o mais fácil. Coloquei o multímetro em modo de continuidade, para testar continuidade (óbvio), e testei nos quatro pinos se um deles estava conectado ao ground da placa, geralmente o GND está ligado nas carcaças metálicas. E foi isso mesmo, pino 3 dando continuidade com um parafuso da placa, indicando realmente ser o GND.

VCC. Agora, em modo de medir tensão, conectei a ponta de prova preta ao GND que descobri (pino 3) e a vermelha no pino 1. Marcou 3.34v me indicando que provavelmente aquele era o VCC mesmo. Não dava pra ter certeza, mas a marcação da placa no meu caso, isolando um pouco mais esse pino e demarcando com “1”, já me dava certa confiança. Esse pino só é importante encontrar, para que não seja confundido com um TX ou RX, já que não vamos utilizar o VCC.

TX e RX. Aqui a coisa começa a ficar complicada. Se você tiver um osciloscópio acho que facilitaria, pois seria possível medir as oscilações desses pinos, já que é uma comunicação serial, esses pinos ficam ligando e desligando muito rapidamente, enviando os bits da comunicação. Como não tinha nenhuma ferramente ideal para medição, fui no multimetro barato mesmo. Ao medir identifiquei que os dois pinos ficavam em 3.3v ao ligar a câmera (ponta preta no GND e vermelha no pino que eu queria medir).

Pois bem isso poderia indicar duas coisas, ou é o pino TX ou RX e o meu multímetro por ser mais lento não consegue medir as variações de tensão causadas pela taxa de comunicação ser alta, ou um dos dois pode ainda ser o VCC, já que eu não tinha ainda certeza.

Fiz um teste desligando a câmera enquanto media os pinos. Ao desligar com o multimetro conectado, tanto ao pino 2, quanto ao pino 4, a tensão ia a zero imediamente, indicando, pra mim, fim de comunicação.

Ao fazer o mesmo teste com o multimetro no pino 1 (VCC) a tensão não ia a zero imediatamente, mas ainda permaneciam alguns milivolts por alguns segundos antes de ir a zero. Pra mim, indicando algum capacitor ainda em descarga e me dando mais certeza de que aquele era mesmo o VCC, logo sobravam os pinos 2 e 4 como TX e RX, ainda não sabendo qual era qual.

Fim da história, soldei 3 fios, preto no pino 3 (GND), verde no pino 2 e laranja no pino 4. Como ainda não tinha certeza qual era o RX e qual era o TX, resolvi ligar e testar assim mesmo.

USB to TTL (usando um NodeMCU queimado!)

Vocês devem saber que para fazer uma comunicação serial com o computador é necessário um conversor USB-TTL, que é bem fácil de achar pra comprar e bem barato.

Por exemplo: https://s.click.aliexpress.com/e/_A88LJ0

Mas eu não estava com paciência de esperar.

Na internet encontrei alguns posts falando que é possível utilizar o arduino como USB-TTL. E isso me deu umas idéias.

Como tinha aqui em casa arduino uno, esp32 e esp8266, os últimos dois embarcados nas famosas placas nodemcu, que já possuem embutidos os chips conversores para comunicação serial com o USB do computador, de forma que você consegue facilmente espetar seu ESP diretamente no USB e sair programando pra ele sem se incomodar com conversores (Olha só!)

Caso queira comprar um nodemcu desse, vou deixar o link de onde você pode comprar. Compro sempre no aliexpress, demora um pouco pra chegar, entre 20 a 30 dias, mas vem certinho.

Nodemcu: https://s.click.aliexpress.com/e/_AkN0OS

Detalhe importante: como o esp8266 embarcado no meu nodemcu estava queimado e não funcionava mais, resolvi fazer umas experiências com ele.

Como ao conectar o nodemcu no usb ele ainda reconhecia, isso indicava pra mim que o conversor USB-Serial dele ainda estava funcionando. Apenas o esp8266 é que tinha morrido, então se eu tentasse, por exemplo, enviar algum código pra ele, ele não respondia.

Logo, a idéia foi remover completamente o esp8266 do nodemcu e utilizar o conversor de lá, ligando os fios correspondentes ao GND, TX e RX deiretamente. Para remover, utilizei o estanhador mesmo, não é o indicado, mas não tinha outro meio. Alguns pinos foram arrancados, mas os que eu precisava ficaram instactos, ainda bem.

ESP8266 removido (veja que na foto já tem os fios ligados, Verde: TX, Laranja: RX, Preto: GND):

Abaixo a ligação dos fios nos pinos correspondentes. Essa imagem demonstra como encontrei os pinos no nodemcu. Isso foi muito fácil pois embaixo do esp8266 tinha já a marcação de cada pino, então, foi só olhar onde estava ligado e soldar. Bem fácil.

Preto: GND, Verde: TX, Laranja: RX

Ligação do USB-TTL com o UART da Câmera

IMPORTANTE: Um ponto importante é sempre se atentar a tensão dos equipamento que você está conectando. Por exemplo, se você for utilizar um arduíno como conversor USB-Serial nessa câmera, eu recomendaria utilizar um conversor de nível lógico bidirecional de 5v para 3.3v (ou um divisor de tensão), uma vez que o arquino trabalha com 5v, e a câmera, a gente viu que trabalha a 3.3v. Ligar 5v ali poderia danificar a câmera.

No caso do nodemcu, ele já trabalha com 3.3v, pois o esp8266 também trabalha nessa tensão, então tudo perfeito, não precisei fazer nenhuma conversão.

Continuando, a primeira vez que liguei a câmera no nodemcu e liguei no computador, nada aconteceu. Isso porque o RX e o TX estava ligados no mesmo ou seja, RX com RX e TX com TX. O Correto é ligar ao contrário, RX com TX e TX com RX.

GND deve ser ligado com GND. Não esqueça dele.

Fonte da imagem: https://medium.com/@shubhamgolam10/reverse-engineering-uart-to-gain-shell-de9019ae427a

Mascomo vimos, eu nem sabia quem era o TX e o RX da câmera. Descobri quando não funcionou e ao inverter funcionou. rsrsrs Não sei se pode ocorrer algum problema ao ligar isso invertido, mas no meu caso nada foi danificado.

Então ficou assim:

  • Fio preto da camera(GND) ligado ao preto do nodemcu
  • Fio Verde da camera (TX) ligado ao laranja do nodemcu (RX)
  • Fio Laranja da camera (RX) ligado ao verde do nodemcu (TX)

Lendo a comunicação Serial

Uma das dúvidas que eu tinha era como ler essa comunicação no computador. Primeiro fui no velho conhecido arduino IDE, selecionei a porta onde o nodemcu modificado estava conectado, e abri o serial monitor. Se conhece o arduino sabe do que estou falando.

Incrível ver como aquilo não tinha funcionado. Primeiro, por que nada aconteceu, então resolvi inverter o fios do tx e rx, como mencionando acima. Depois disso, vualá, um monte de caracteres estranhos começaram a aparecer na tela:

Isso me indicava uma coisa,o tal do BAUD RATE estava errado.

Descobrindo o BAUD RATE

Não vou explicar exatamente o que é isso, mas em resumo, é a velocidade de comunicação que está sendo utilizada naquela comunicação. Se você programa arduino já viu que é possível definir a taxa desejada que você quer utilizar na comunicação. Logo, fui testando outras ali no monitor serial do arduino até aparecer alguma coisa legível.

Existem outras formas de descobrir o baud rate, inclusive tem algumas formas nos links que coloquei ali em baixo nas referências. Mas eu achei mais fácil do jeito que fiz.

Em resumo, e pelo que vi a grande maioria das câmeras utilizam baud rate de 115200.

Selecionando a porta correta e definindo o baud rate correto, é possível verificar o que a câmera envia pela comunicação serial.

Um detalhe importante, esse print da imagem acima, eu fiz depois de a câmera já estar funcionando corretamente. Antes, a mensagem que ocorria na parte do “Uncompressing Linux… done, booting the kernel.” era um erro mais ou menos assim:

Uncompressing Linux…undefined instruction

Por isso a câmera não ligava mais, pois tinha alguma coisa corrompida no firmware atual.

Usando o Minicom

Para que fosse possível acessar o serial como se fosse um terminal e executar comandos na câmera foi necessário utilizar um outro software, no meu caso utilizei o minicom, como estou utilizando o Ubuntu acabei achando mais fácil. A instalação é trivial, com um simples sudo apt install minicom e está tudo certo.

Se você estiver no mac, pode usar o minicom também e instalar via homebrew. Se estiver no windows, não sei dizer ao certo, mas acho que não tem minicom. Então vai ter que achar alternativas como o putty, senão estou enganado.

Como vimos, nossa comunicação está funcionando a partir do dispositivo /dev/ttyUSB0 que é onde plugamos o usb com o nodemcu. sabendo disso podemos acessar o minicom digitando no terminal:

minicom -D /dev/ttyUSB0

Não esqueça de fechar o serial monitor do arduino, senão pode ter um erro como abaixo:

minicom: cannot open /dev/ttyUSB0: Device or resource busy

Enfim, você deve conectar o USB-TTL e iniciar o minicom sem ligar a câmera. O Minicom irá conectar na interface USB e aguardar comunicação. Ao ligar a câmera, verá os dados que a câmera envia diretamente no seu terminal:

Agora, preste atenção onde eu marquei com essa linda seta. Esta dizendo para pressionar CTRL + C para interromper o autoboot.

Isso quer dizer que se der ctrl+c antes do boot começar, ele interrompe o boot e te dá acesso ao prompt da câmera. E ISSO É FANTÁSTICO!

Uma dica é ficar apertando CTRL+C antes de ligar e enquanto liga a camera na energia, senão é difícil de conseguir antes do autoboot.

Ao entrar no prompt alguns comandos ficam disponíveis, no exemplo da imagem, digitei help e pressionei enter. O resultado é uma lista de comandos disponíveis no sistema da câmera.

Vou falar sobre alguns importantes:

setenv – set environment variables

Utilizaremos para alterar algumas variáveis de ambiente, como por exemplo, o serverip, que será o ip do servidor tftp que iremos configurar.

run – run commands in an environment variable

É um comando interessante, afinal, nos diz que roda comandos que estão armazenados em variáveis de ambiente. Isso significa que existem variáveis de ambiente que possuem comandos a serem executados!

printenv – print environment variables

Exibe pra nós a lista das variáveis de ambiente, você verá como isso é importante, pois teremos que alterar algumas variáveis mais tarde, para que nosso processo funcione corretamente, e também veremos as variáveis com os comandos que devemos executar.

Sobre as variáveis de ambiente, notamos algumas como ipaddr, que contém o ip atual da camera, serverip, que seria o servidor de tftp que ela irá utilizar na horas de buscar os arquivos para fazer o update, e também existem algumas muito interessantes como é o caso dos da, dc, dr, etc.

Se você perceber, o conteúdo delas é uma série de comandos específicos. Por exemplo, vamos analisar o conteúdo da variável da:

da=mw.b 0x81000000 ff 800000;tftp 0x81000000 u-boot.bin.img;sf probe 0;flwrite

Parece estar dizendo para fazer um memory write (mw.b) começando em 0x81000000 do ‘ff’ até os próximos 800000 bits, e então executar um tftp (conectando no servidor definido na variável serverip) buscando o arquivo u-boot.bin.img começando a escrever em 0x81000000 e então verifica o dispositivo no bus 0 e finalmente grava na flash com o flwrite.

Vendo isso, percebemos que será necessário ter os arquivos .img para serem gravados, e também precisamos de um servidor tftp para deixar esses arquivos disponíveis e, só então executar esses comandos utilizando o comando run (run commands in an environment variable).

Baixando os arquivos do firmware

Aqui vai depender da sua câmera, você terá que identificar qual fabricante, modelo e tudo isso, e tentar encontrar os arquivos no site da fabricante.

No meu caso, a Besder, que é a marca onde comprei a câmera, possui como fabricante a xiongmaitech, que também tem várias outras marcas vendendo os mesmo produtos, só que com marca diferente, bem típico, rsrs.

Então, se tiver com uma câmera da xiongmaitech, os passos serão bem parecidos, senão vai ter que ver como encontrar por você mesmo. Se não for, eu nem sei se esses passos todos funcionarão.

Se você quiser saber se sua câmera é uma xiongmai, talvez esse post possa ajudar:

https://sec-consult.com/en/blog/2018/10/millions-of-xiongmai-video-surveillance-devices-can-be-hacked-via-cloud-feature-xmeye-p2p-cloud/#BlogPostXiongmai(XMeyeP2PCloud)-HowtoidentifyaXiongmaidevice

Identificando o modelo do seu dispositivo

Identifique o modelo exato da sua câmera. No meu caso, eu tenho duas câmeras idênticas, logo, consegui entrar nas informações do dispositivo da que funciona e pegar essas informações conforme a imagem, se você não tem outra que funciona pra ver isso, pra ser sincero, eu não sei como fazer.

Bem entrando nas configurações da câmera no ICSee consigo ver essas informações conforme abaixo:

Veja onde sublinhei, são a versão do dispositivo e a versão do software. Essas informações sublinhadas você vai precisar para encontrar seu firmware corretamente.

Então no meu caso:

Versão do dispositivo: 50X20-WG

Versão do software: Aqui precisamos apenas do 000309c1

Encontrando o firmware correto do seu dispositivo

Eu encontrei no site da xiongmaitech a página de download de drivers. Porém, tem que ser na versão em chinês, já que a versão em inglês do site não tem nada pra download.

Dessa forma, ativei a tradução para inglês no chrome mesmo, e fui procurando pelo drive que eu queria.

Link para download: http://www.xiongmaitech.com/service/down_detail1/13/2/5

No meu caso, estava na página 5. Então tente identificar o correto para o seu modelo. Não tente se não for exatamente a do seu modelo!

Perceba que está exatamente a versão do dispositivo e a versão do software que encontramos anteriormente no nome do arquivo a ser baixado.

Será baixado um arquivo como este:

000309C1.1IPC_XM530_50X20-WG_WIFIXM711.711.Nat.dss.OnvifS_V5.00.R02.zip

É um arquivo compactado que se descompactado ficará assim:

General_IPC_XM530_50X20-WG_WIFIXM711.711.Nat.dss.OnvifS_V5.00.R02.20200917_all.bin

Um arquivo bin é como um arquivo compactado, nesse caso, caso sua câmera estiver funcionando, você pode atualizar ela diretamente pela interface web dela ou pelo próprio app como o ICSee, informando esse arquivo .bin.

Porém, no meu caso, não está funcionando, se tivesse eu não estaria passando por todo esse trabalho, não é mesmo?

Dessa forma, para que possamos gravar o firmware, teremos que fazer isso por partes. Como falei, o arquivo .bin nada mais é do que um arquivo compactado, no mac e no linux, é possível descompactar normalmente, no windows, não tenho certeza, mas se renomear a extensão para .zip será possível descompactar também.

Os arquivos descompactados ficarão assim:

Perceba que temos vários arquivos .img que iremos gravar na nossa câmera.

O Arquivo InstallDesc possui os passos a serem seguidos para a atualização. Imagino que a atualização via interface web utilize esse arquivo como configuração de execução do update.

Instalando o servidor TFTP para servir os arquivos da atualização

Como comentei, para atualizar a câmera, é necessário que ela possua uma maneira de baixar facilmente esses arquivos para atualizar. A forma que essas câmeras utilizam é a transferência dos arquivos via TFTP.

TFTP é uma forma de transferência de arquivos geralmente utilizada em redes, e tem um conceito de simplicidade, não necessitando sequer um usuário e senha para ter acesso aos arquivos.

Para instalar o servidor no linux utilizei o passo a passo deste post: https://linuxhint.com/install_tftp_server_ubuntu/

Para outros SOs como Mac ou Windows também devem existir servidores TFTP facilmente configuráveis.

O requisito principal é que os arquivos de firmware extraídos estejam disponíveis através do TFTP. Então coloque todos eles na raiz do seu servidor TFTP, por exemplo, se a pasta a qual seu servidor TFTP serve é /usr/tftp, como no meu caso, então coloque os arquivos diretamente lá dentro, sem subdiretórios.

Para testar se está funcionando, você pode tentar acessar o tftp e baixar algum dos arquivos, por exemplo, usando o client TFTP no ubuntu (192.168.2.144 é o IP do computador onde eu instalei o servidor do TFTP, no caso o meu próprio computador):

[email protected]:~$ tftp 192.168.2.144
tftp> get u-boot.bin.img
Received 196756 bytes in 0.1 seconds
tftp> q
[email protected]:~$ ls
Desktop Documents Downloads Music Pictures Public snap Templates u-boot.bin.img Videos

É interessante você verificar se o firewall do seu computador não está bloqueando o acesso a partir de outra máquina na rede.

Se deu certo pra você e conseguiu baixar o arquivo como no exemplo, podemos seguir para o próximo passo!

Aplicando a atualização

Lá em cima, onde falei das variáveis de ambiente já dei um spoiler do que deve ser feito. Mas vamos ver com calma passo a passo agora.

Primeiro, temos que garantir que a câmera está conectada na rede e que consegue acessar o serviço do tftp.

Primeiro, conecte sua câmera no cabo ethernet.

Depois, configure as variáveis de ambiente ipaddr com o ip que será atribuído para a câmera e o serverip com o ip onde instalamos e configuramos nosso servidor tftp que servirá os arquivos para atualização. Para definir as variáveis de ambiente utilize o setenv.

setenv ipaddr 192.168.2.999
setenv serverip 192.168.2.144

No meu caso deixei a câmera com o IP fixo 192.168.2.999, de forma que não de conflito com outros dispositivos, e configurei o serverip com o IP 192.168.2.144 que é o IP do meu computador onde está instalado e configurado o servidor de TFTP.

Agora basta salvar as alterações com saveenv.

saveenv

Agora você deve digitar o comando reset, que irá reiniciar a câmera. Não esqueça do CTRL + C para entrar novamente no U-Boot.

reset

É interessante também verificar se o nosso servidor está acessível pela câmera. Pra isso podemos usar o ping! Verifique se o resultado diz que o host que você digitou “is alive”!

ping 192.168.2.144

Agora, vamos avaliar o arquivo InstallDesc que descompactamos junto com os arquivos do firmware:

{
	"UpgradeCommand":	[{
			"Command":	"Burn",
			"FileName":	"u-boot.bin.img"
		}, {
			"Command":	"Burn",
			"FileName":	"u-boot.env.img"
		}, {
			"Command":	"Burn",
			"FileName":	"custom-x.cramfs.img"
		}, {
			"Command":	"Burn",
			"FileName":	"uImage.img"
		}, {
			"Command":	"Burn",
			"FileName":	"romfs-x.cramfs.img"
		}, {
			"Command":	"Burn",
			"FileName":	"user-x.cramfs.img"
		}],
	"Hardware":	"XM530_50X20-WG_8M",
	"DevID":	"000309C11001000000600000",
	"WifiDriverType":	"xm711",
	"CompatibleVersion":	3,
	"Vendor":	"General",
	"CRC":	"802001675000",
	"Mx8Q":	"vS8ufwq7xiPTLLQoLObf+qMAcyr7M3GevHMxdFYPHJk4z4DLsle1330VhYxCMpPMqBqZYVVt+zm9NZ10FlH2p/YuDkCcYM0GsRPq0nWOP7DlS13Owwa+G/7vxIwTYD9m4gJNXNclaTIzHln1K1GRarwE9qMIJiV9r1pbwwba887TWv4="
}

Nesse arquivo podemos ver o passo a passo a ser seguido para aplicar a atualização. Cada Command Burn, indica um arquivo .img que deve ser gravado. Perceba que todos esses arquivos estão presentes no mesmo arquivo que baixamos do firmware.

Imagino que seja muito interessante seguir exatamente essa ordem definida nesse arquivo ao atualizarmos

Vamos entrar novamente no minicom e acessar a câmera. Novamente, vamos analisar as variáveis de ambiente que temos no sistema da câmera, utilizando o comando printenv:

Acho que agora ficou bem mais claro o que expliquei lá em cima sobre as variáveis de ambiente “da”, “dc”, “dr”, “du”, certo?

Muito bem, o que precisamos fazer agora, é avaliar o seguinte, baseado no arquivo InstallDesc:

  • O primeiro arquivo que devemos gravar é: u-boot.bin.img, então nesse caso podemos rodar os comandos da variável “da”, que vai baixar esse arquivo.
run da
  • O Segundo arquivo é u-boot.env.img. Neste caso, e no meu caso pelo menos, nenhuma variável de ambiente referencia esse arquivo. Logo, o que eu fiz foi criar um baseado nos outros comandos, seguindo exatamente o mesmo padrão. Lendo o resultado, percebi um erro de can`t write to protected Flash sectors. Porém mesmo assim segui em frente. O comando ficou assim:
mw.b 0x81000000 ff 800000;tftp 0x81000000 u-boot.env.img;sf probe 0;flwrite
  • O terceiro arquivo é o custom-x.cramfs.img. Este está referenciado na variável de ambiente “dc”. Então basta rodar diretamente a variável com o comando:
run dc
  • O quarto arquivo uImage.img, também não está presente em nenhuma das variáveis de ambiente. Importante, esqueça a variável “tk” mesmo ela tendo uma referência a uImage, ela não grava nada, só dá boot no sistema utilizando uma imagem existente, pelo que entendi. Então criei novamente um comando para gravação dessa imagem, que foi executado com sucesso:
mw.b 0x81000000 ff 800000;tftp 0x81000000 uImage.img;sf probe 0;flwrite
  • O quinto arquivo, romfs-x.cramfs.img, é referenciado na variável “dr”, então:
run dr
  • E o sexto e último arquivo, user-x.cramfs.img, é referenciado na varíavel “du”. Mais um simples:
run du

Se tudo deu certo, você pode simplesmente dar um reset novamente, e deixar a câmera ligar normalmente. No meu caso o erro “Uncompressing Linux…undefined instruction” desapareceu e a câmera voltou a vida.

Sucesso rapazeada!

Referências

Alguns posts que encontrei e foram muito úteis:

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *