Como quebrar uma câmera cara para que sua esposa não o mate

Isenção de responsabilidade: o estudo começou em 2013, então se você acha que alguns métodos são estúpidos e perigosos - você está certo, foi isso. No entanto, aprendi muito no processo.

Entrada
Tudo começou alguns meses antes do nascimento do meu primeiro filho. Minha esposa e eu sempre quisemos comprar uma câmera Leica legal e de repente percebemos que, se não comprássemos agora, não poderíamos fazer isso por um longo tempo. Por isso, pedimos a câmera M240 e ... boom, fomos colocados na fila por seis meses. Logo estava cansado de esperar e comecei a estudar o site deles. Minha atenção foi imediatamente atraída para a seção de arquivos. Bem, você pode adivinhar por que ... Firmware!

Vi um arquivo não criptografado e descompactado ( m8-2_005.upd ) que começa com a magia PWAD . Você reconhece? Sim, está certo, este é o formato Doom Patch WAD. Caras parecem amar os clássicos. O formato está muito bem documentado , por isso não foi difícil analisá-lo.

Arquivos de firmware Leica


Firmware Leica M8


Isso é realmente muito engraçado, porque quando mais tarde estudei o arquivo de firmware Leica T compactado, decidi primeiro verificar os métodos de compactação que o ID usava no passado.

A Wikipedia diz que eles usaram o formato LHA , que é essencialmente o LZW. Mas os descompressores LZW comuns não se encaixavam, então comecei a procurar uma implementação específica do software de identificação - e pronto, encontrei o Catacomb Armageddon na fonte . Devo admitir, com sorte.

De qualquer forma, volte ao M8. Aqui está a estrutura do firmware:

  REGRAS: 0x0000008C (3036: 0x00000BDC) - descrição XML
 LUTS: 0x00000C68 (183274: 0x0002CBEA)
  GAMMA: 0x0000007C (31760: 0x00007C10)
  GANHO: 0x00007C8C (50344: 0x0000C4A8)
  LEICA: 0x00014134 (7000: 0x00001B58)
  BLEMISH: 0x00015C8C (250: 0x000000FA)
  WREF: 0x00015D88 (82480: 0x00014230)
  OBJ: 0x00029FB8 (11268: 0x00002C04)
  VERSÃO: 0x0002CBBC (46: 0x0000002E)
 PXA: 0x0002D854 (858384: 0x000D1910)
 BF: 0x000FF164 (134522: 0x00020D7A) - família de processadores Analog Devices Blackfin
 GUI: 0x0011FEE0 (3574180: 0x003689A4)
  TRANS: 0x0000005C (59988: 0x0000EA54) - localização
  IMAGENS: 0x0000EAB0 (267433: 0x000414A9)
   21_1PRT: 0x000000CC (18411: 0x000047EB) - foto de JFIF
   21_2GRP: 0x000048B8 (23172: 0x00005A84) - imagem de JFIF
   21_3PAN: 0x0000A33C (23034: 0x000059FA) - imagem de JFIF
   24_1PRT: 0x0000FD38 (18489: 0x00004839) - imagem de JFIF
   24_2GRP: 0x00014574 (23230: 0x00005ABE) - imagem de JFIF
   24_3PAN: 0x0001A034 (22998: 0x000059D6) - imagem de JFIF
   28_1PRT: 0x0001FA0C (22605: 0x0000584D) - foto de JFIF
   28_2GRP: 0x0002525C (23081: 0x00005A29) - imagem de JFIF
   28_3PAN: 0x0002AC88 (23282: 0x00005AF2) - imagem de JFIF
   35_1PRT: 0x0003077C (22496: 0x000057E0) - imagem de JFIF
   35_2GRP: 0x00035F5C (23532: 0x00005BEC) - foto de JFIF
   35_3PAN: 0x0003BB48 (22881: 0x00005961) - imagem de JFIF
  FONT1: 0x0004FF5C (1522988: 0x00173D2C)
  FONT2: 0x001C3C88 (1723676: 0x001A4D1C)
  VERSÃO: 0x003689A4 (0: 0x00000000)
 M16C: 0x00488884 (130406: 0x0001FD66) - família Renesas M16C (Motorola S-record)
 FPGA: 0x004A85EC (131604: 0x00020214) - Xilinx Spartan 3
 FSL: 0x004C8800 (814: 0x0000032E) - o primeiro carregador de inicialização do estágio 

O IDA pronto para uso não suporta processadores Blackfin, mas há um plug-in de terceiros .

Firmware Leica M9


O arquivo de firmware Leica M9 ( m9-1_196.upd ) parece criptografado: o histograma mostra uma distribuição de cerca de 0,45%.



O fim da história? Talvez não. O fato é que a Leica usava processadores bastante fracos nas câmeras e, na época, a criptografia XOR era frequentemente usada em eletrônicos de consumo, então decidi escrever uma ferramenta simples para a operação do XOR para comparar o firmware comigo e calcular algumas estatísticas.

O comprimento da chave foi determinado procurando o padrão de repetição mais longo. Isso faz sentido, pois qualquer firmware geralmente inclui grandes blocos de dados repetidos, como um bloco 0x00 / 0xFF ou gráficos com pixels LUT. A chave em si é calculada pela frequência de bytes dentro do comprimento da chave, onde o byte mais comum vai para o buffer da chave. O resultado do programa indicou claramente a criptografia XOR. Então tive que modificar um pouco a ferramenta para obter a chave potencial e descriptografar o código. Novamente, isso acabou sendo um arquivo PWAD.

O conteúdo do PWAD revelou a seguinte estrutura:

  REGRAS: 0x0000007C (2788: 0x00000AE4) - descrição XML
 LUTS: 0x00000B60 (4060616: 0x003DF5C8)
  PROCESSO: 0x0000004C (3900572: 0x003B849C)
   CREATE: 0x0000004C (20: 0x00000014) - registro de data e hora
   LUTS: 0x00000060 (427744: 0x000686E0)
   GAINMAP: 0x00068740 (20008: 0x00004E28)
   LENTE: 0x0006D568 (3452724: 0x0034AF34)
  CCD: 0x003B84E8 (148662: 0x000244B6)
   CREATE: 0x0000004C (20: 0x00000014) - registro de data e hora
   BLEMISH: 0x00000060 (1092: 0x00000444)
   WREF: 0x000004A4 (147452: 0x00023FFC)
   LIN: 0x000244A0 (22: 0x00000016)
  ICCPROF: 0x003DC9A0 (4304: 0x000010D0)
   ECI-RGB: 0x0000003C (540: 0x0000021C)
   sRGB: 0x00000258 (3144: 0x00000C48)
   A-RGB: 0x00000EA0 (560: 0x00000230)
  WBPARAM: 0x003DDA70 (7000: 0x00001B58)
 BF561: 0x003E0128 (289128: 0x00046968) - família de processadores Analog Devices Blackfin
  bf0: 0x0000004C (117846: 0x0001CC56) - processador principal
  bf1: 0x0001CCA4 (117826: 0x0001CC42) - firmware do subprocessador
  bf0.map: 0x000398E8 (27072: 0x000069C0) - placa de firmware do processador principal com caracteres: D
  bf1.map: 0x000402A8 (26304: 0x000066C0) - placa de firmware do subprocessador com caracteres: D
 CORPO: 0x00426A90 (143280: 0x00022FB0) - família Renesas M16C (Motorola S-record)
 GUI: 0x00449A40 (3647624: 0x0037A888)
  TRANS: 0x0000005C (131656: 0x00020248) - localização
  IMAGENS: 0x000202A4 (267433: 0x000414A9)
   21_1PRT: 0x000000CC (18411: 0x000047EB) - foto de JFIF
   21_2GRP: 0x000048B8 (23172: 0x00005A84) - imagem de JFIF
   21_3PAN: 0x0000A33C (23034: 0x000059FA) - imagem de JFIF
   24_1PRT: 0x0000FD38 (18489: 0x00004839) - imagem de JFIF
   24_2GRP: 0x00014574 (23230: 0x00005ABE) - imagem de JFIF
   24_3PAN: 0x0001A034 (22998: 0x000059D6) - imagem de JFIF
   28_1PRT: 0x0001FA0C (22605: 0x0000584D) - foto de JFIF
   28_2GRP: 0x0002525C (23081: 0x00005A29) - imagem de JFIF
   28_3PAN: 0x0002AC88 (23282: 0x00005AF2) - imagem de JFIF
   35_1PRT: 0x0003077C (22496: 0x000057E0) - imagem de JFIF
   35_2GRP: 0x00035F5C (23532: 0x00005BEC) - foto de JFIF
   35_3PAN: 0x0003BB48 (22881: 0x00005961) - imagem de JFIF
  FONT1: 0x00061750 (1522988: 0x00173D2C)
  USBLOGO: 0x001D547C (1775: 0x000006EF) - foto de JFIF
  FONT2: 0x001D5B6C (1723676: 0x001A4D1C)
 FPGA: 0x007C42C8 (150176: 0x00024AA0) - Xilinx Spartan 3A
 BF547: 0x007E8D68 (937576: 0x000E4E68) - Família de processadores Analog Devices Blackfin (FSL?) 


Firmware Leica M240


Eu adquiri o hábito de verificar a página de download com o firmware Leica todas as manhãs. Logo apareceu um novo arquivo: FW_M240_1_1_0_2.FW .

Não parecia criptografado, mas estava compactado ...

Compressão


O histograma mostra uma enorme explosão em 0x9D.



Talvez isso seja algum tipo de mágica de compressão. Uma pesquisa na Internet [compressão 9D +] não resultou em nada, exceto que 0x1F9D é usado como assinatura da compactação LZW . Se alguma coisa, eu entendo os tipos de compressão LZ e decidi olhar para os bytes após 0x9D. E vi quatro opções:

  1. 9D 70 C4
  2. 9D 00
  3. 9D XX YY
  4. 9D XX 8Y YY

O que mais você conseguiu notar:

  • a primeira opção aparece apenas uma vez no endereço 0x30: provavelmente é usada como um indicador de dados compactados;
  • XX nunca excede 0x7F;
  • o último byte de YY no terceiro e quarto casos nunca excede 0x7F

Pelo que sei sobre LZ, isso é muito semelhante ao LZ77 ou LZSS, onde YY é a etapa de recuo e XX é o número de bytes a serem copiados. E a segunda opção é um caso especial de emissão de 0x9D. Eu escrevi uma função C simples que implementa essa lógica. Ela confirmou que estamos caminhando na direção certa, mas a quarta opção ainda não se encaixa no esquema.

Eu tentei de todas as maneiras interpretá-lo, mas nada aconteceu. Portanto, voltei-me para meus companheiros em busca de conselhos. Um cara percebeu que, de acordo com minhas próprias observações, o quarto byte de YY aparece apenas quando o bit mais alto 0x8Y é definido: essa é apenas uma distância extra para a etapa de recuo. Eu tinha vergonha, tudo ficou tão óbvio ...

Finalmente, o descompactador começou a emitir um fluxo válido ... até ficar preso no meio do arquivo. Isso aconteceu devido ao comprimento desconhecido da janela deslizante. Depuração e testes adicionais corrigiram a situação.

Portanto, havia uma ferramenta para analisar o firmware M240 .

Estrutura de firmware


Para trabalhar com um formato desconhecido, não criei nada melhor do que medir alguns desvios e tamanhos de seções de código - e tentar encontrar os valores mais próximos no cabeçalho do arquivo. Por exemplo, este bloco:

0x00: 1E 1C AF 2E 01 01 00 02 07 E1 EA 5E 00 5C 1A B1
0x10: 01 29 1A 7E AE 38 73 65 9C 3D 75 B4 34 2F 44 6E
0x20: 13 17 8E 6B 00 00 00 01 00 00 00 30 E1 E3 50 D1


acabou se transformando em:

1E1CAF2E — "LEICA FILE"
01010002 - 1.1.0.2
005C1AB1 — (big endian)
01291A7E — (big endian)
AE3873659C3D75B4342F446E13178E6B — MD5
00000001 —
00000030 —


Como entendi a estrutura do firmware, aprimorei minha ferramenta e, no final, ela produziu o seguinte:

Running with options:
+ firmware folder: M240_FIRMWARE
+ verbose enabled

Open firmware file: FW_M240_1_1_0_2.FW
File size: 6036193 | 0x005C1AE1

Parse container header:
version: 1.1.0.2
packed size: 6036145 | 0x005C1AB1
unpacked size: 19470974 | 0x01291A7E
body blocks: 1 | 0x00000001
body offset: 48 | 0x00000030
MD5: AE387365 9C3D75B4 342F446E 13178E6B
MD5 check: PASSED

Uncompress container body:
6036145 -> 19470974
Uncompression: DONE

Split container:
Number of sections: 9 | 0x00000009
Section table size: 612 | 0x00000264
Section table offset: 36 | 0x00000024
Section 1
Section Name: "[A]IMG_LOKI-212"
Section offset: 0 | 0x00000000
Section size: 7340032 | 0x00700000
Section base: 1048576 | 0x00100000
MD5: A8D55AA2 B0ACDB14 0673AD79 707674F3
MD5 check: PASSED
Create file: M240_FIRMWARE/IMG_LOKI-212.bin

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Section 9
Section Name: "[A]IMG-LENSDATA-213"
Section offset: 19214844 | 0x012531FC
Section size: 255478 | 0x0003E5F6
Section base: 16252928 | 0x00F80000
MD5: 39C2BEC0 27ED23F6 2C1C8513 EEE697B9
MD5 check: PASSED
Create file: M240_FIRMWARE/IMG-LENSDATA-213.bin
Splitting container: DONE
Extraction COMPLETE!


O firmware M240 inclui um contêiner com nove elementos:

IMG_LOKI-212.bin -
IMG_LOKI-213.bin -
CTRL_SYS-11.bin - -
IMG-FPGA-212.bin - ()
IMG-FPGA-213.bin - ()
IMG-DSP-212.bin - DSP
IMG-DSP-213.bin - DSP
IMG-LENSDATA-212.bin -
IMG-LENSDATA-213.bin -


Como você pode ver, em um firmware, existem dois conjuntos de arquivos. Mais tarde, soube que 212 é uma versão do microcircuito de processamento de imagens e duas versões do Leica M240 foram produzidas. Este estudo é baseado na versão 212.

Gerenciamento do sistema: CTRL_SYS-11.bin


A única parte comum é o firmware do chip de controle do sistema. Este é um binário muito grande, e o código pode adivinhar com facilidade o que se destina.

$ strings CTRL_SYS-11.bin | rg SH
-> Test SH7216 data flash driver
-> Test SH7216 SCI driver
-> Test SH7216 I2C driver
-> Test SH7216 MTU2 driver
-> Test SH7216 ADC functions
-> Test SH7216 CMT driver


Portanto, temos o processador Renesas SH7216 (SH-2A), responsável pelo estágio inicial de carregamento, testes de E / S e atualizações de firmware. Pronto para uso O IDA suporta esse tipo de processador. Restou apenas encontrar o endereço de carga base correto, conhecido pela descrição das seções de firmware: este é 0x0 .

Section Name: "[A]CTRL_SYS-11"
Section offset: 14680064 | 0x00E00000
Section size: 917277 | 0x000DFF1D
Section base: 0 | 0x00000000


Carreguei-o no IDA e reconheci todas as funções, mas não o mergulhei especialmente, porque o firmware do processador principal é muito mais interessante.

Aqui também é possível notar que o UART desse chip é aberto na porta de serviço, onde ele exibe o log de download. Voltaremos a isso mais tarde.

Chip principal: IMG_LOKI-212.bin


Para iniciar a engenharia reversa deste firmware, você deve primeiro responder a algumas perguntas:

  1. que tipo de processador
  2. qual é o endereço de carga base
  3. em que sistema operacional se baseia, se houver

Graças à nossa ferramenta, já sabemos o endereço da carga base: este é 0x100000 .

Section Name: "[A]IMG_LOKI-212"
Section offset: 0 | 0x00000000
Section size: 7340032 | 0x00700000
Section base: 1048576 | 0x00100000


O firmware armazena as respostas restantes em um formato legível. Por exemplo, esta linha:

$ strings ./IMG_LOKI-212.bin | rg Softune
6Softune REALOS/FR is Realtime OS for FR Family, based on micro-ITRON COPYRIGHT(C) FUJITSU LIMITED 1994-1999
...


Portanto, estamos lidando com um processador personalizado Fujitsu FR (a Leica chama Maestro ) e o sistema operacional Softune REALOS . De fato, isso é muito melhor que o Blackfin, porque o IDA pronto para uso suporta FR.

Módulo do processador FR


A realidade não era tão clara, porque após o download do arquivo de firmware, o programa IDA não mostrou instruções, links externos etc.

Decidi corrigi-lo, mas no final tive que reescrever completamente algumas partes do firmware . Aqui está o resultado:





Além das correções em ana , ins e out , um código de emu completamente novo pode:

  • reconhecer vários tipos de código e links externos para dados;
  • Reconhecer instruções de opção
  • executar rastreamento de pilha;
  • Argumentos de pilha separados e variáveis ​​locais
  • reconhecer as funções corretamente.

Mas a maior mudança, como você notou, são letras maiúsculas para obter instruções :)

Deseja ver o conjunto completo de instruções? Aqui está:

  ADD OU BTSTH LSR MOV BN LDRES EXTSH   
 ADD2 ORH MUL LSR2 JMP BP STRES EXTUH   
 ADDC ORB MULU ASR CHAMADA BV COPOP SRCH0   
 ADDN EOR MULH ASR2 RET BNV COPLD SRCH1   
 ADDN2 EORH MULUH LDI INT BLT COPST SRCHC   
 SUB EORB DIV0S LDI INTE BGE COPSV LDM0    
 SUBC BANDL DIV0U LDI RETI BLE NOP LDM1    
 SUBN BANDH DIV1 LD BRA BGT ANDCCR STM0    
 CMP BORL DIV2 LDUH BNO BLS ORCCR STM1    
 CMP2 BORH DIV3 LDUB BEQ BHI STILM ENTER   
 E BEORL DIV4S ST BNE DMOV ADDSP SAIR   
 ANDH BEORH LSL STH BC DMOVH EXTSB XCHB    
 ANDB BTSTL LSL2 STB BNC DMOVB EXTUB 

Então, simples e bonito.

A propósito, você deve ter notado que algumas instruções não estão alinhadas:

  BRA: D loc_xxx
     LDI: 8 # 0x64, R5 

Isso não é um erro no módulo do processador, mas de fato um recurso da família Fujitsu FR. É chamado de slot de atraso e é bastante típico para processadores RISC.

No manual do processador FR80 (nota: o link não funciona mais):

A instrução localizada imediatamente após a instrução da filial (sua localização é chamada de "slot de atraso") é executada antes da filial e a instrução no endereço de destino é executada após a filial. Como a instrução no slot de atraso é executada antes da operação de ramificação, a velocidade de execução aparente é de 1 ciclo.

Portanto, essa é, em essência, a otimização do pipeline, e é melhor lembrá-lo, porque é usado em qualquer lugar do firmware Leica.

Softune REALOS


Do wiki :

Softune é o ambiente de desenvolvimento integrado da Fujitsu para as famílias de processadores Fujitsu FR, FR-V e F2MC. Desenvolvido com o kernel em tempo real REALOS µITRON. Por exemplo, é usado nas câmeras Nikon DSLR (consulte Nikon EXPEED) e em algumas câmeras Pentax com K.

Portanto, este é um RTOS decente bastante popular, com tarefas, semáforos e outras guloseimas. Gostaria de saber se é possível reconhecer algumas funções padrão da biblioteca no firmware Leica.

Eu tenho que chamar a primeira parte do estudo de uma grande perda de tempo, e aqui está o porquê.

O IDE do Softune acabou sendo muito difícil de encontrar, mas no final consegui obter alguma coisa. Como esperado, o IDE incluiu bibliotecas. Havia quatro binários:

  • lib911.lib
  • lib911e.lib
  • lib911if.lib
  • lib911p.lib

Não sei por que, talvez por inércia, ao cortar tudo relacionado à Leica, comecei a engenharia reversa do formato novamente. Sim, um formato de módulo de objeto muito bem documentado. E sim, é claro, escrevi uma ferramenta especial para isso :

Fujitsu RISC Library Tool v1.0
Usage: FRLibTool [-s start] [-i imagebase] [-o output] [-f index] [-dv] FIRMWARE.BIN LIBRARY.LIB

This tool will help you to find Softune REALOS library functions in FR (Fujitsu RISC) firmware.
Use following arguments:
-f Specify firmware image file
-s Specify firmware image scan offset
-b Specify firmware imagebase
-o Specify output type (exclusively)
list - list of functions
idc - IDC script
py - IDA python script
pat - FLAIR pattern file
-i xxx Specify index of particular function
-d Dump library
-v Be verbose


Com ele, você pode criar arquivos *.pat e usá-los como entrada no IDA FLAIR para gerar arquivos de assinatura .

$ FRLibTool -o pat lib911.lib
$ FRLibTool -o pat lib911e.lib
$ FRLibTool -o pat lib911if.lib
$ FRLibTool -o pat lib911p.lib
...
$ sigmake -n "SOFTUNE C/C++ Library" lib911.pat lib911e.pat lib911if.pat lib911p.pat softune.sig


Depois de aplicar esta assinatura, finalmente vi a correspondência em IMG_LOKI-212.idb .



Layout


O número de linhas no firmware atrai imediatamente a atenção. Muitas funções são nomeadas por sua funcionalidade. Isso é muito útil no processo de engenharia reversa para entender o padrão geral.

Também é importante observar que algumas partes do arquivo de firmware são copiadas para um endereço diferente no manipulador de redefinição. Por exemplo, o carregador interno em tempo de execução move-se mais alto na RAM.

Eu tive que criar manualmente seções adicionais, como resultado, obtive o seguinte layout:



Interrupções


A tabela de vetores de interrupção pode ser encontrada acessando o TBR (Table Base Register):

LDI:32 #int_table, R0
MOV R0, TBR


Geralmente, ocorre no manipulador de redefinição de vetor no início do firmware.

Os endereços dos manipuladores na tabela são armazenados na ordem inversa, de acordo com a fórmula TBR + (0x3FC - 4 × inum) , portanto, o vetor de redefinição no final da tabela é compensado em 0x3FC .

Encontrei a maioria das interrupções no manual do FR e sugeri que o Leica Maestro tivesse um layout semelhante. Em seguida, ele pegou cada manipulador e tentou encontrar uma string ou qualquer outra dica que revelasse o objetivo da interrupção.

Como resultado, fiz esta lista:



Muitas interrupções são bastante esperadas, como AUDIO / SDIO / VIDEO / JPEG / RAW, mas tentam identificar as mais misteriosas delas? Estou falando de interromper int_uart_in . Parece que a câmera suporta algum tipo de UART CLI no modo de console.

Chamadas do sistema


Como quase qualquer sistema operacional, o Softline REALOS usa chamadas do sistema. No assembler, eles ficam assim:



O endereço real do manipulador de chamadas do sistema é calculado da seguinte maneira. Vamos começar procurando o manipulador de interrupção INT #0x40 . Como descrito acima, esse

(0x3FC - 4 × inum) = (0x3FC - 4 × 0x40) = 0x2FC = int_realos_syscall

No manipulador, é fácil encontrar um link para a parte inferior da tabela de chamadas do sistema com palavras de 16 bits. O registro específico nesta tabela é calculado pela fórmula syscall_table_bottom + (num * 2) :

[syscall_table_bottom + (-23 * 2)] = [syscall_table_bottom - 0x2E] = [0x1012EA] = 0xE68

Isso não parece um endereço, porque o endereço real do manipulador de chamadas do sistema é calculado como syscall_table_bottom + offset . Todo o processo é mostrado no diagrama.



Todas as chamadas do sistema e suas funcionalidades são indicadas no manual do kernel da Softline REALOS / FR ; portanto, consegui restaurar todos os manipuladores implementados na tabela e melhorar um pouco mais o BID.



Obviamente, você pode tornar o código ainda mais bonito definindo os tipos de chamadas do sistema no IDA.



Eu escrevi um script Python para procurar automaticamente essas chamadas do sistema e muito mais.

As tarefas


Na chamada do sistema sta_tsk notei que não a função principal é passada como parâmetro, mas pid. Isso significa que é hora de procurar uma grande variedade de descritores de tarefas. E faz sentido começar com o próprio sta_tsk .

  ROM: 102180 sys_sta_tsk:
 ROM: 102180 ST RP, @ -R15
 ROM: 102182 LDUB @ (R14, 0x4F), R3
 ROM: 102184 LDI: 32 # word_100B80, R14 

No início, vemos alguns links. Eu tive que mexer um pouco nos tipos de dados, mas no final as peças se uniram:

  ROM: 100B80 word_100B80: .word 0xF;  número de tarefas
 ROM: 100B82. Palavra 0x1C;  tamanho do descritor de tarefas

 ROM: 100B84. 0x82A09F5C;  tarefa 1 descritor
 ROM: 100B88 .long 0x1000D
 ROM: 100B8C .long 0
 ROM: 100B90 .long 0x40000000
 ROM: 100B94 .long sub_1A7DB2;  tarefa principal
 ROM: 100B98 .long 0x8286EEC0
 ROM: 100B9C .long 0

 ROM: 100BA0. 0x82A09F88;  tarefa 2 descritor
 ROM: 100BA4 .long 0x20010
 ROM: 100BA8 .long 0
 ROM: 100BAC .long 0x40000000
 ROM: 100BB0 .long sub_1A6BD2;  tarefa principal
 ROM: 100BB4 .long 0x8287EEC0
 ROM: 100BB8 .long 0
 ... 

e assim por diante. Apenas 15 tarefas. Era questão de tempo examinar cada função principal, determinar o nome e o objetivo da tarefa (exceto a última). Aqui está a lista completa:

  1. SubCPU
    Essa tarefa é aparentemente responsável por operações de captura, como exposição, observação na tela etc.
  2. Keymanager
    Provavelmente, esta tarefa está associada aos botões de hardware.
  3. Guimanager
    Uma grande tarefa, na qual a máquina de estado da interface do usuário e a renderização da interface são implementadas.
  4. Gerenciador de Depuração
    Sim, há algo para depurar. Yum yum.
  5. Gerenciador de arquivos
    Esta tarefa é sobre operações de arquivo.
  6. Fammanager
    Eu diria que a tarefa é responsável pelos arquivos e memória, porque depende das tarefas do gerenciador de arquivos e do gerenciador de memória.
  7. Gerenciador de memória
    Sem surpresas: operações de memória, gerenciamento de pool, etc.
  8. Imagemanager
    Esta tarefa gerencia os processos de codificação / decodificação e outros processos de processamento de imagem.
  9. Usbmanager
    O desafio atual é o processamento de comunicações USB, que inclui o MassStorage, PTP e o próprio protocolo da Leica.
  10. IOManager
    Essa tarefa parece estar gerenciando dispositivos de armazenamento, como cartões SD e CF (o que? Que outros CFs? Talvez seja do modelo 213).
  11. Systemmanager
    Várias tarefas, como operações gerais do sistema, gerenciamento de energia, etc.
  12. SettingsManager
    Lida com o status e as configurações da câmera.
  13. Monitormanager
    Rastreia as alterações no estado da câmera e informa outras tarefas.
  14. Gerenciador de periféricos
    Esta tarefa controla o GPS, o brilho e alguns outros sensores.
  15. Desconhecido
    Infelizmente, não encontrei nada significativo para ela.

É interessante notar que, após a matriz principal, existe outro descritor excelente.

ROM:100D28 dword_100D28: .long 0x82A0A1F0
ROM:100D2C .long 0x21
ROM:100D30 .long 0
ROM:100D34 .long 0x80000000
ROM:100D38 .long tid16_task
ROM:100D3C .long 0x8285EEC0
ROM:100D40 .long 0


E a função da tarefa é simplesmente se ramificar.

ROM:101494 sub_101494:
ROM:101494 BRA sub_101494 ; CODE XREF: sub_101494


Esse descritor é mencionado no final da função de start , responsável por criar outras tarefas e configurar o firmware. Portanto, essa é provavelmente a tarefa da inação do sistema.

Módulos e Mensagens


Além das tarefas, você pode definir alguns objetos lógicos, como E / S e módulos periféricos. Os módulos são apresentados como um grupo de manipuladores de mensagens como parte de uma das tarefas.

O grupo de E / S parece incluir:

  • Gerente de IO
  • Subprocessador
  • Gerenciador USB
  • PTP USB
  • Protocolo USB Leica
  • Armazenamento em massa USB
  • Button Manager
  • Gerenciador de depuração
  • Gerenciador de lentes

E no grupo periférico:

  • Gerenciador de periféricos
  • Sensor de luz
  • LEDs
  • Orador
  • Sensor de inclinação
  • Reconhecimento de fechamento de boné
  • Módulo GPS
  • Módulo 3DAxis

O próprio sistema de mensagens usa as estruturas SOFTUNE padrão:

 struct RealOS_MsgPayload { uint32_t msgID; // +0x0 uint32_t data[]; // +0x4 } struct RealOS_Message { uint32_t os_reserved1; // +0x0 uint32_t os_reserved2; // +0x4 uint32_t to; // +0x8 uint32_t from; // +0xC RealOS_MsgPayload* payload; // +0x10 } 

Como esperado, o IPC também possui vários grupos de mensagens. Como muitas mensagens são processadas em tarefas e módulos, consegui recuperar apenas alguns desses grupos:

  0x1101xxxx - mensagens do sistema global:
              0x11010002 = SYS_UPDATE_BOOTLOADER ou
              0x11010005 = SYS_ERASE_SETTINGS
 0x1102xxxx - mensagens relacionadas à captura de imagem:
              0x11020001 = CMD_CAP_CAPTURE ou
              0x11020008 = IMAGE_STATUS_CHANGED  
 0x1104xxxx - mensagens sobre eventos relacionados à reprodução:  
             0x11040002 = PLY_DISABLE_PLAY_MODE 
             0x11040004 = PLY_IMAGE_READY  
0x1108xxxx -     PTP  .:
             0x11080002 = DBG_CHANGE_LEVEL 
             0x11080012 = DBG_WRITE_ROM_DUMP_SD  
0x2201xxxx -  USB PTP
             0x22010108 =    
             0x22010118 =  DebugObject  
0x2202xxxx -     SUBCPU:
             0x22020002 = E_SUBCPU_REQUEST_M_EXPOSURE_REQUEST  
             0x22020015 = E_IO_SUBCPU_COMMAND_CLEANING_SENSOR  
0x2203xxxx -    :
             0x22030001 =   
0x2204xxxx -   IO:
             0x2204000C = / Mass Storage 
             0x22040012 =    
0x330000xx -     UI:
             0x33000001 =  
             0x33000007 =  
0x440000xx -   ,     
             0x44000013 = E_IMG_CMD_CHANGE_PINFO  
0x55xxxxxx —   FAM:  
             0x558800xx = - FAM 
             0x558888xx =     FAM
0x6602xxxx —     LED, :
             0x66020001 -  LED  X 
             0x66020002 =   LED  
0x6604xxxx -  :
             0x66040001 =  
             0x66040007 =    
0x6611xxxx -  ,   
0x6622xxxx -   ,   
0x6660xxxx - algumas outras mensagens relacionadas à memória:
             0x66600006 = HISTOGRAMA  
             0x66600011 = RAWCOMP  
0x771100xx e 0x77AA00xx - mensagens relacionadas à troca de modos da câmera 

Infelizmente, muitos outros posts permanecem desconhecidos.

GUI


No arquivo de firmware, veremos também as seguintes seções: CTRL_SYS-11 , IMG-LOKI-212 , IMG-DSP-212 , IMG-FPGA-212 e IMG-LENSDATA-212 .

O que me surpreendeu foi a completa falta de recursos da GUI. Mas eles devem estar em algum lugar e, provavelmente, estão incorporados no IMG-LOKI-212 .

Uma das minhas abordagens usuais para reverter o desenvolvimento de firmware é restaurar todas as referências cruzadas possíveis. Não apenas no código, mas também na seção de dados. Então eu os olho, tentando encontrar alguns padrões ou links para partes conhecidas do código.

O firmware Leica não foi exceção. Existem muitas sequências de dados semelhantes com endereços para outras sequências de dados que vão além, etc. Ao escalar a hierarquia de links, finalmente vi uma função familiar.

Por exemplo, encontrei uma estrutura de dados sem links:

 g_data = { ... } 

Outra estrutura abordou:

 g_data_struct1 = { ... , &g_data } 

Que por sua vez é referido por outra estrutura:

 g_data_struct2 = { &g_data, ... } 

Essa estrutura de dados tem um link do código e é passada como parâmetro para outra função:

 func1() ╰ func2(..., &g_data_struct2, ...) 

No entanto, func1()não é chamado diretamente de outra função, mas é armazenado em alguma matriz:

 g_func_list1[] = { ..., func1(), ... } 

Olhando acima, encontrei uma chamada no código g_func_list1:

 func3() { g_func_list1[x] } 

E, novamente, essa função é armazenada em uma matriz:

 g_func_list2[] = { ..., func3(), ... } 

Algum outro código acessa a própria matriz:

 func4() { g_func_list2[x] } 

Felizmente, desta vez a função é chamada de outra função e assim por diante gui_MADE_ApplicationRun.

 gui_Statemachine_DoStateChange() ╰ gui_MADE_ApplicationRun() ╰ func5() ╰ func4() 

Algumas linhas indicam que o subsistema da GUI é chamado "MADE" e as transições de página são manipuladas usando MADE_GetSysTrio que isso significa. A máquina de estado da GUI é basicamente implementada em uma função gui_Statemachine_DoStateChange. Após coletar informações sobre a GUI, a figura geral se desenvolveu:



Como você pode ver, a principal função dos recursos da GUI é gui_CopyImageDesc(embora esse não seja um nome real). Ela tem os seguintes argumentos:

 gui_CopyImageDesc( uint32_t dstAddress; // R4 - destination address UIDescType type; // R5 - description type UITarget target; // R6 - rendering target uint32_t descAddress; // R7 - description address uint8_t always0; // (SP + 0x0) - always 0 uint8_t index1; // (SP + 0x4) - index 1 uint8_t index2; // (SP + 0x8) - index 2 uint16_t x_offset; // (SP + 0xC) - x offset uint16_t y_offset; // (SP + 0x10) - y offset uint16_t unknown2; // (SP + 0x14) - uint32_t language1; // (SP + 0x18) - language id 1 uint32_t language2; // (SP + 0x1C) - language id 2 uint32_t funcAddress; // (SP + 0x20) - function address ) 

Existem quatro tipos de descrições de recursos:

 struct UIDescType0Header struct UIDescType1Header struct UIDescType2 struct UIDescType3 { { { { uint32_t address; uint32_t address; uint32_t reg; uint16_t x_offset; uint16_t entries; uint16_t entries; uint32_t address; uint16_t y_offset; uint16_t unknown; uint16_t unknown; uint16_t unknown1; uint32_t address; } } uint16_t unknown2; } uint16_t unknown3; struct UIDescType0Entry struct UIDescType1Entry uint16_t tableoff; { { } uint16_t x_offset; uint16_t x_offset; uint16_t y_offset; uint16_t y_offset; uint32_t address; uint32_t address; } uint16_t objects; uint16_t total_w; uint16_t total_h; uint16_t unknown; } 

O primeiro tipo tem um cabeçalho com uma referência a uma matriz de registros. Cada registro possui coordenadas e um endereço para dados de pixel. O tipo atual parece descrever elementos dependentes do estado, como ícones, que podem ficar acinzentados ou desaparecer da interface do usuário.

O segundo tipo também começa com um cabeçalho e é usado para localizar, descrever linhas ou blocos de texto.

O terceiro tipo descreve mapas de caracteres para diferentes idiomas.

O último tipo é responsável por todos os outros recursos estáticos, como imagens, planos de fundo etc.

Agora, vamos dar uma olhada nos dados das próprias imagens. Os primeiros seis bytes parecem um cabeçalho pequeno, seguido por algum tipo de padrão repetitivo, em que cada segundo byte é ou . É lógico supor que e

+0x00: 00 08 00 14 00 01 A2 FF 0A 04 05 FF 0C 04 03 FF
+0x10: 0D 04 03 FF 0E 04 02 FF 0E 04 02 FF 04 04 06 FF
+0x20: 04 04 02 FF 04 04 06 FF 04 04 02 FF 04 04 06 FF
+0x30: 04 04 02 FF 04 04 06 FF 04 04 02 FF 04 04 06 FF
+0x40: 04 04 02 FF 04 04 06 FF 04 04 02 FF 04 04 06 FF
+0x50: 04 04 02 FF 04 04 06 FF 04 04 02 FF 0E 04 02 FF
+0x60: 0E 04 02 FF 0D 04 03 FF 0D 04 03 FF 0C 04 04 FF
+0x70: 04 04 0C FF 04 04 0C FF 04 04 0C FF 04 04 0C FF
+0x80: 04 04 0C FF 04 04 0C FF 04 04 0C FF 04 04 0C FF
+0x90: 04 04 0D FF 02 04 2D FF 00 06 00 14 00 01 79 FF


0xFF0x040x00080x0014- largura e altura em uma exibição com ordem direta de bytes (big endian). No final deste despejo, vemos o início de outra sequência 00 06 00 14 00 01. Provavelmente, este é o próximo recurso (conforme confirmado por um link para ele). Assim, o tamanho dos dados reais da imagem é 146 bytes. Mas o tamanho da imagem deve ser 0x8 * 0x14 = 0xA0 = 160. É claro que os dados não são pixels puros e nem mesmo uma LUT de 8 bits, porque são 14 bytes menores. Então o que?Provavelmente algum tipo de compressão.

Olhando para esse despejo hexadecimal, é difícil acreditar que algum tipo de esquema complexo seja usado. A GUI da Leica não é muito colorida, portanto, na minha experiência, é melhor usar a tabela LUT aqui. Nesse caso, os recursos da interface do usuário repetirão completamente os índices LUT como 03 03 03ou 1 1 1. Normalmente, o compressor tenta se livrar da duplicação de dados, substituindo-os por um link. Essas matrizes de índice são ideais para compactação, mesmo com um método simples como o RLE [data][number]. Um comando simples para escrever data(valor) numbervezes.

Com tudo isso em mente, sugeri que provavelmente observamos uma imagem simples com duas cores LUT ( 0xFFe 0x04), e o byte na frente da cor é o número de pixels a serem desenhados.

"E então você escreveu outro instrumento", você pensa. Mas não, peguei caneta e papel e comecei a preencher as células. É engraçado que eu ainda tenha essa foto.



Em algum lugar ao longo do caminho, percebi que 160 pixels não são suficientes para esta imagem; portanto, 0x8 e 0x14 precisam ser multiplicados por dois. A terceira palavra 0x0001 indica se a imagem é um caractere ASCII, portanto a estrutura final do ImageAsset é a seguinte:

 struct ImageAsset { uint16_t width; // /2 (big endian) uint16_t height; // /2 (big endian) uint16_t ascii; // 1,   ASCII struct image_data { uint8_t number; //     uint8_t color; //     LUT } data[]; } 

Mas ainda falta uma parte: LUT.

Não foi tão difícil de encontrar, porque muitos links e estruturas já foram restaurados manualmente, então eu rolei lentamente as seções de dados, procurando uma matriz de 256 elementos a partir de valores de 16 ou 32 bits, até me deparar com isso: Mais uma vez, obrigado No meu trabalho com o Blackmagic Design, reconheci imediatamente os pixels YUV (por exemplo, todos os valores com os números 8080). Não sou idiota de desenhar novamente toda a interface do usuário manualmente no papel, então sim, escrevi outra ferramenta - M240UITool . Além de redefinir todos os recursos de imagem do arquivo de firmware para BMP / PNG, essa ferramenta pode criar scripts IDC no IDA para determinar todos os recursos da interface do usuário.

.long 0x7008080, 0x72D8080, 0x73C8080, 0x75A8080, 0x79B8080, 0x71DFF6B, 0x7BE8080, 0x7FF8080
.long 0x77BBD27, 0x75B60E7, 0x7835F4A, 0x7D3089F, 0x7018080, 0x7028080, 0x7038080, 0x7048080
.long 0x7058080, 0x7068080, 0x7078080, 0x7088080, 0x7098080, 0x70A8080, 0x70B8080, 0x70C8080
.long 0x70D8080, 0x70E8080, 0x70F8080, 0x7108080, 0x7118080, 0x7128080, 0x7952B15, 0x7138080
.long 0x7148080, 0x7158080, 0x7168080, 0x7178080, 0x7188080, 0x7198080, 0x71A8080, 0x71C8080
.long 0x71D8080, 0x71E8080, 0x71F8080, 0x7338080, 0x7208080, 0x7218080, 0x7228080, 0x7238080
.long 0x7248080, 0x7248080, 0x7268080, 0x7278080, 0x7288080, 0x7298080, 0x72A8080, 0x72B8080
.long 0x72C8080, 0x75E8080, 0x7608080, 0x7628080, 0x7648080, 0x7678080, 0x7688080, 0x7698080
.long 0x76B8080, 0x76E8080, 0x7708080, 0x7728080, 0x7758080, 0x7778080, 0x7798080, 0x77C8080
.long 0x77E8080, 0x7818080, 0x7838080, 0x7868080, 0x7888080, 0x78B8080, 0x78D8080, 0x7908080
.long 0x7928080, 0x7958080, 0x7978080, 0x7998080, 0x79C8080, 0x79D8080, 0x7668080, 0x79E8080
.long 0x7A18080, 0x7A28080, 0x7A38080, 0x7A68080, 0x7A78080, 0x7A88080, 0x7AB8080, 0x7AC8080
.long 0x7AD8080, 0x7B08080, 0x7B28080, 0x7B58080, 0x7B88080, 0x7B98080, 0x7BC8080, 0x7CC8080
.long 0x7AB3BBB, 0x7E10094, 0x7E4556E, 0x4008080, 0x2922D17, 0x7B2AB00, 0x7C2A262, 0x71DFF6B
.long 0x768D4A2, 0x769D4EA, 0x7BD88AE, 0x705997B, 0x70BB377, 0x711CC73, 0x717E66F, 0x7238866
.long 0x729A262, 0x72FBB5E, 0x735D55A, 0x7417751, 0x747914D, 0x74DAA48, 0x753C444, 0x75F663B
.long 0x76B9933, 0x7998080, 0x771B32F, 0x77D5526, 0x7836F22, 0x789881E, 0x78FA21A, 0x7159095
.long 0x71AAA91, 0x720C38D, 0x726DD88, 0x7506F6A, 0x7568866, 0x75CA262, 0x762BB5E, 0x76E5E55
.long 0x7747751, 0x77A914D, 0x780AA48, 0x78C4D3F, 0x792663B, 0x7988037, 0x79E9933, 0x7AA3C2A
.long 0x7B05526, 0x7B66F22, 0x7BC881E, 0x72488AE, 0x72AA1AA, 0x72FBBA6, 0x735D4A2, 0x7427799
.long 0x7489095, 0x74DAA91, 0x753C38D, 0x77E556E, 0x7836F6A, 0x7898866, 0x78FA262, 0x79C4459
.long 0x7A15E55, 0x7A77751, 0x7AD914D, 0x7BF4D3F, 0x7CC8080, 0x7C5663B, 0x7CB8037, 0x7337FC8
.long 0x73999C4, 0x73FB2C0, 0x745CCBB, 0x7757799, 0x74C54FF, 0x77B9095, 0x780AA91, 0x7AB3C72
.long 0x7B1556E, 0x7B66F6A, 0x7BC8866, 0x74277E1, 0x74890DD, 0x74EAAD9, 0x754C3D5, 0x76066CC
.long 0x7667FC8, 0x76C99C4, 0x772B2C0, 0x77E55B7, 0x7846EB3, 0x78A88AE, 0x790A1AA, 0x7526EFB
.long 0x75787F7, 0x75DA1F3, 0x763BAEE, 0x76F5DE6, 0x77577E1, 0x77B90DD, 0x781AAD9, 0x78D4CD0
.long 0x79366CC, 0x79F99C4, 0x7E10094, 0x7CF44A1, 0x7DB7799, 0x7E71A90, 0x7ED338C, 0x7FF8080
.long 0x7328080, 0x7DC8080, 0x7C88080, 0x7508080, 0x775CD2C, 0x76944EA, 0x7808080, 0x71A61FF
.long 0x7244D40, 0x7242C15, 0xFFF8080, 0xF338080, 0xF668080, 0xF998080, 0xFCC8080, 0xF008080
.long 0xF4C54FF, 0xFAB3BBB, 0xFE10094, 0xFE4556E, 0xF952B15, 0xFDA7751, 0xFB2AB00, 0xFC2A262
.long 0xF1DFF6B, 0xF68D4A2, 0xF69D4EA, 0xFBD88AE, 0xA922D17, 0xC6E4130, 0xE286963, 0x74C55FF
.long 0x768D536, 0x7FF8080, 0x7FF8080, 0x7FF8080, 0x2922D17, 0x46E4130, 0x6286963, 0x8080






Leica M (typ 240) UI Tool v1.0
Usage: ./M240UITool [-a address] [-i imagebase] [-s script] [-d dump] [-f folder] [-l LUT] [-rbv] FIRMWARE.BIN

This tool will help you to find UI resources in firmware.
Use following arguments:
-a Specify address of the gui_CopyImageDesc function (ex. 0x2F95E0)
-i Specify firmware imagebase
-s Specify IDC file name
-c Specify container file name
-d Specify dump image format
png - PNG format
bmp - BMP (ARGB) format
-f Specify folder for dumped images
-l Specify LUT for images (filename of address)
-b Specify number of bytes to display in verbose mode
-r Try to recover string characters
-v Be verbose




Já sabemos que, a partir da função que uma página da interface do usuário cria, ela é chamada várias vezes gui_CopyImageDesc. Eu pensei que seria ótimo criar um navegador de recursos da interface do usuário e definir todos os recursos de renderização da página. A opção -cé destinada a isso - ele cria um contêiner especial para visualizar recursos.

E quem disse que um navegador de recursos da interface do usuário pode não parecer incomum?



Sendo interativa (botões translúcidos na captura de tela), essa ferramenta permite não apenas rolar pelas páginas do menu EVF / LCD, mas também visualizar as etapas de renderização em uma página.

Infelizmente, o código fonte desta obra-prima foi perdido em algum lugar, mas os arquivos de cabeçalho ainda estão no código M240UITool, portanto, tecnicamente, você pode recriá-lo do zero.

Menu Debug


Que linha procuramos principalmente quando fazemos engenharia reversa? Na minha opinião, esta palavra debuge seus derivados.

Havia muitas linhas interessantes no firmware, mas estas são especiais: Parece que você pode entrar no modo de depuração usando alguma combinação de teclas. Todas essas linhas são chamadas de uma função gigante , que implementa uma máquina de estado de verificação de botão. Aqui está o que parece na AID:

$ strings ./IMG_LOKI-212_1.1.0.2.bin | grep "Debug Mode"
GUI: State: %d! Scanning for Debug Mode successful
GUI: Scanning for Debug Mode: State: %d, Ignore long DEL
GUI: Scanning for Debug Mode: State: %d
GUI: Scanning for Debug Mode: State: %d, Ignore long DEL
GUI: Scanning for Debug Mode: State: %d
GUI: Scanning for Debug Mode: State: %d, Ignore long DEL
GUI: Scanning for Debug Mode: State: %d
GUI: Scanning for Debug Mode: State: %d, Ignore long DEL
GUI: Scanning for Debug Mode: State: %d
GUI: Scanning for Debug Mode: State: %d, Ignore long DEL
GUI: Scanning for Debug Mode: State: %d
...
GUI: ScanningForDebugWithKeyAndJoyStick(): g_GUI_CheckForDebugWithKeyAndJoyStick = %d


ScanningForDebugWithKeyAndJoyStick



Não vou mentir, demorou algum tempo para entender como os botões de hardware são processados ​​no firmware e depois restaurar os tipos enumerados para os botões e o joystick. Mas quando recebi a combinação, descobri com pesar que ela não estava fazendo nada. Provavelmente só funciona em uma página específica da GUI. Mais algumas noites de rastreamento manual da máquina de estado da GUI - e o problema foi resolvido, e também conseguimos encontrar a página de menu Redefinir.

Finalmente, bem-vindo ao modo de depuração.



Pensei muito em anunciar essa combinação, mas decidi me abster. Respeito o trabalho árduo que a Leica realiza, liberando seus dispositivos exclusivos, e não quero ser responsável pelo fato de que seus centros de serviço preencherão as carcaças quebradas das câmeras como resultado de alguma curiosidade impensada.

Mas, ainda assim, fornecerei alguns tipos enumerados para simplificar a engenharia reversa para aqueles que estão prontos para seguir esse caminho.

 enum ControlActionType { kControlAction_Idle, // 0 kControlAction_Push, // 1 kControlAction_Release, // 2 kControlAction_LongPush // 3 }; enum ControlBtnType { kControlBtn_LV, // 0 kControlBtn_PLAY, // 1 kControlBtn_DEL, // 2 kControlBtn_ISO, // 3 kControlBtn_MENU, // 4 kControlBtn_SET // 5 }; enum ControlJoystickType { kControlJoy_INFO, // 0 kControlJoy_Up, // 1 kControlJoy_Down, // 2 kControlJoy_Left, // 3 kControlJoy_Right // 4 }; 

Ptp


Pensando na tarefa USB, defini três modos (o que também é confirmado no menu de depuração):

  • Ptp
  • MSC (Classe de Armazenamento em Massa)
  • Leica custom

O PTP é mais interessante porque está bem documentado e permite controlar a câmera.

É bastante fácil encontrar manipuladores de PTP no firmware, porque há muitas chamadas desse código. Todas as chamadas de PTP são divididas em três grupos: Legado , Leica Extended (LE) e Produção .

A depuração de mensagens ajudou a estabelecer nomes para quase todo o código.

 Legado: Leica Extensão: Produção:                           
0x1001 - GetDeviceInfo 0x9001 - Definir configurações da câmera 0x9100 - Abrir sessão de produção      
0x1002 - OpenSession 0x9002 - Get Camera Settings 0x9101 - Close Production Session     
0x1003 - CloseSession 0x9003 - Get Lens Parameter 0x9102 - UpdateFirmware               
0x1004 - Get Storage ID 0x9004 - Release Stage 0x9103 - Open OSD Session             
0x1005 - Get Storage Info 0x9005 - Open LE Session 0x9104 - Close OSD Session            
0x1006 - GetNumObjects 0x9006 - Close LE Session 0x9105 - Get OSD Data                 
0x1007 - GetObjectHandles 0x9007 - RequestObjectTransferReady 0x9106 - GetFirmwareStruct            
0x1008 - GetObjectInfo 0x9008 - GetGeoTackingData 0x910B - GetDebugMenu                 
0x1009 - GetObject 0x900A - Open Debug Session 0x910C - SetDebugMenu                 
0x100A - Get Thumb 0x900B - Close Debug Session 0x910D - ODIN Message                 
0x100B - Delete Object 0x900C - Get Debug Buffer 0x910E - GetDebugObjectHandles        
0x100E - Initiate Capture 0x900D - Debug Command String 0x910F - GetDebugObject               
0x1014 - GetDevicePropDesc 0x900E - Get Debug Route 0x9110 - DeleteDebugObject            
0x1015 - GetDevicePropV 0x900F - SetIPTCData 0x9111 - GetDebugObjectInfo           
0x101C - Initiate Open Capture 0x9010 - GetIPTCData 0x9112 - WriteDebugObject             
                                   0x9020 - Get3DAxisData 0x9113 - CreateDebugObject            
                                   0x9030 - OpenLiveViewSession 0x9114 - Calibrate 3Daxis             
                                   0x9031 - CloseLiveViewSession 0x9115 - Magnetic calibration         
                                   0x9033 - Unknown 0x9116 - Get Viewfinder Data 

A implementação da interface PTP em si parece padrão, mas alguns comandos têm limitações que eu intencionalmente omito aqui.

De qualquer forma, todas as opções acima são bastante emocionantes. Você pode pensar: "Vamos conectar a câmera via USB e começar a pesquisar com a libptp". Isso mesmo.

Droga ... O

Leica M240 não possui uma porta USB.

Lidar com porta


A Leica oferece poucos acessórios para esta câmera, mas há um especialmente interessante. Estamos falando do cabo multifuncional Leica M (14495) . Ele substitui a parte de metal inferior do gabinete, fornece GPS embutido e vários conectores como USB, um terminal flash SCA, DIN / ISO-X e uma tomada.



E você diz novamente: “Ótimo, agora compre, conecte-o à câmera, conecte-a via USB e comece a pesquisar usando o libptp.” Isso mesmo.

Só que droga ...

Custa quase 900 dólares.

São quase novecentas razões para criar seu próprio adaptador. No entanto, por precaução, configurei as notificações do eBay para este acessório.

Conector


O conector da câmera é o seguinte:



tentei encontrá-lo na Internet, mas, falando sério, como você o descreveria no Google?

Desesperado, comecei a pensar em algumas coisas malucas, como colar papel alumínio ou agulhas na borracha. Mas, uma vez trabalhando no Blackmagic Design, olhando para a placa de circuito da câmera, notei que um dos conectores tinha um formato muito familiar. No dia seguinte, trouxe meu Leica M240 para trabalhar - e sim, parecia semelhante, por muito mais tempo com muitas almofadas.

Resta perguntar o número de peça do nosso gerenciador de componentes e, em seguida, localizá-lo no catálogo da Samtec: ERM8-013-05.0-L-DV-TR .



Também perguntamos à Samtec se era possível obter uma amostra e eles concordaram.



Um pouco de trabalho com um ferro de solda, papelão e fita isolante - e meu próprio plugue está pronto (amostra de 2013).



Cinco anos depois, em 2018, decidi pedir pessoalmente à Samtec para enviar outra amostra. Eu queria fazer algo melhor.

ERCD-013-05.00-TTR-TTR-1-D


Mais uma vez, muito trabalho com um ferro de soldar, praguejar, cortar arame, praguejar, novamente trabalhar com um ferro de soldar para criar uma opção nova e mais atraente:



Pinagem


Existem 26 contatos no conector: 13 de cada lado. Mesmo antes de soldar minha peça, eu testei o conector da câmera com um multímetro e um analisador lógico. A propósito, você precisa colocar um ímã no sensor da tampa inferior para que a câmera considere que a tampa está no lugar.

Terra (câmera desligada, sem bateria)

Eu sempre começo do chão porque é seguro e muito fácil de encontrar.



Assim, temos oito linhas de fundo (cinza escuro).

Potencial (câmera ligada)

Quando a câmera está ligada, você pode medir o potencial em cada pino e ter uma idéia dos níveis de lógica e potência.

alexhude.imtqy.com/assets/2019/2019-01-24-hacking-leica-m240/probe2_potential.png

O desempenho nos pinos 8–9 e 11–13 é muito alto para os pinos lógicos, então eu os defini como potência (vermelho).

Resistência (câmera desligada, sem bateria)

É útil medir a resistência. Em alguns casos, isso ajuda a identificar as entradas e agrupar algumas linhas.



Saídas conectadas (câmera desligada, sem bateria)

Decidi verificar todas as almofadas externas no corpo da câmera para verificar se estão conectadas à porta de serviço.



O contato de sincronização do flash foi conectado diretamente à linha 10.

Analisador lógico (câmera ligada) Os

dados de cada linha foram gravados na seguinte sequência: ligue-a, a câmera deve estar no modo LV, tirar uma foto e iniciar a gravação de vídeo.



Duas linhas mostram a transmissão de alguns dados: 01 e 21.

01 - 115200, transmissão de 8 bits, 1 bit de parada, bit de paridade, LSB primeiro.



A cada 500 ms, ele envia um contador C3 3C 02 81 00 01 00 82, C3 3C 02 81 01 01 00 83, C3 3C 02 81 02 01 00 80...

21 - 115200, transmissão de 8 bits, 1 bit de parada, sem bit de verificação de paridade, primeiro o LSB.



Ele envia o log do carregador de inicialização para o SH7216 (“Leica Camera AG” na captura de tela acima).

Vamos marcá-los em azul escuro. É muito triste que o registro do Maestro não saia, mesmo com as configurações máximas de depuração no menu Debug.



Nesses contatos, a resistência é de cerca de 310kOhm.

Não sei por que, mas sugeri que outras linhas de dados tenham resistência semelhante ou que serão fechadas. Portanto, eu defini as linhas ~ 300kOhm, ~ 200kOhm e ~ 100kOhm como linhas de dados (tons de azul na imagem).

Em geral, a figura a seguir foi desenhada.



12 candidatos na linha de dados. Mas como verificá-los? Após uma breve conversa com os especialistas em ferro sobre a proteção elétrica de circuitos integrados, comecei a cutucar os contatos através de um resistor de 4kOhm, que reduz a corrente a um nível que as entradas não devem queimar.

UART


Fiz outra suposição de que a linha RX deveria estar perto do TX. As linhas 02, 03 e 20 parecem boas candidatas porque ambas têm uma tensão de 3,3 V como TX.

Inicialmente, tentei explorar essas linhas usando o Bus Pirate. Infelizmente, o resultado foi bastante sujo. Então, peguei os cabos baseados em SiLabs como mais confiáveis ​​e não conflitantes no macOS.

Primeiro, conectei o cabo TX ao pino 20 e comecei a digitar helpapós o carregador de inicialização. Como esperado, após um pequeno atraso, a câmera repetiu os caracteres.



Os contatos 02 e 03 foram os próximos candidatos à UART. Infelizmente, não havia sinais de que essas linhas estavam sendo tocadas.

No diagrama, os UARTs conhecidos são indicados por um tom de verde mais escuro.



USB


Tudo começou com o corte de um cabo USB ao meio, com um cabeçalho no meio e resistores de 4kOhm para detecção. Integridade do sinal de um par diferencial? Não, então eu realmente não me importo. :)



Depois, examinei vários dispositivos domésticos USB em casa para ter uma idéia de como são as comunicações nessa porta.

Canon Camera


Pocket Video Blackmagic


Camcorder Canon


Camcorder JVC


Keychain


Camera Kidizoom


Eles são todos um pouco diferente, mas o estado inicial de D- D + baixa. Bem, vamos saber, e agora vamos verificar se temos:

  • 22 - improvável, porque D-D + é um par diferencial e deve estar bem próximo;
  • 04/05 - é improvável por terem resistência diferente;
  • 14/15 — , ;
  • 15/16 — , .

Conectei o USB D-D + aos pinos 15/16 e o ​​iMac ...



Na tela USB PTP, mas a câmera não apareceu no host. Tentei configurar opções diferentes no layout do circuito eletrônico, mas nada funcionou. O Beagle mostrou muitos pacotes danificados e outros erros. No final, desisti e voltei a fazer engenharia reversa do firmware.

Essa é a pinagem final, o USB está marcado em verde escuro.



Quem pensaria que, alguns anos depois, a mesma notificação do eBay chegaria até mim e comprarei muito barato o acessório desejado.

Finalmente, posso testar minhas suposições sobre PTP. Mas, a princípio, era muito curioso como o USB PHY fica dentro do dispositivo.



Dentro estava o hub SMSC 2512bdiretamente na estrada, desde o conector do cabo até o conector Mini USB. O chip funciona no modo padrão porque não há pinos EEPROM ou SCL / SDA. A primeira porta a jusante é roteada para um soquete no corpo da câmera, mas a segunda não está conectada a nada.

Provavelmente perdi alguma coisa, mas para mim essa solução não faz muito sentido. O passaporte técnico diz que o chip "possui pinos USB totalmente integrados, além de resistores para aumentar e diminuir a tensão". Talvez os engenheiros da Leica tenham decidido não implementar o seu próprio PHY USB, mas usaram o do hub, que é bem testado e funciona imediatamente. Na verdade, não posso culpá-los, porque antes eu tentei fazer isso, e acabou sendo uma tarefa difícil. Talvez esse seja um recurso de proteção contra falsificações, quem sabe.

De qualquer forma, se você entende o USB PHY e está pronto para ajudar, não hesite em me escrever: deve ser possível trabalhar através de uma porta USB sem este acessório de marca :)

PTP novamente


Como eu disse, é hora de brincar com a extensão PTP da Leica.

Felizmente, encontrei uma biblioteca C ++ bem legal em vez do libptp - é o libEasyPTP . Também não demorou muito tempo para escrever uma ferramenta baseada nesta biblioteca: eu já conhecia algumas limitações na interface Leica PTP.

E embora o M240PTPTool seja bastante problemático, ele é adequado para o papel de prova de conceito ( código do programa ).

Apenas duas solicitações passam pelo PTP: GetDebugBuffer (0x900C) e DebugCommandString (0x900D) . A propósito, para que os módulos preencham o log de depuração, você precisa definir o Nível de depuração como "Debug" ou "Debug RAW" no menu.

Existem várias opções na interface M240PTPTool:

  • exit - feche a ferramenta;
  • flush - mescla o buffer de depuração da câmera:

M240> flush
I:[00:11:468]|01| DATE/TIME CORRECTED by 5921 sec
D:[00:12:079]|00| Send message from TID 0 to TID 1 over MBX 3 - length: 4 - MesgID: 0x22020103
D:[00:12:179]|00| Send message from TID 0 to TID 1 over MBX 3 - length: 4 - MesgID: 0x22020103
D:[00:12:282]|11| Message received from TID 0 for TID 1 over MBX 3
D:[00:12:283]|11| Message received from TID 0 for TID 1 over MBX 3
D:[00:12:301]|00| Send message from TID 0 to TID 1 over MBX 3 - length: 4 - MesgID: 0x22020103
D:[00:12:402]|00| Send message from TID 0 to TID 1 over MBX 3 - length: 4 - MesgID: 0x22020103
D:[00:12:502]|00| Send message from TID 0 to TID 1 over MBX 3 - length: 4 - MesgID: 0x22020103
...


Qualquer outro texto é enviado para a câmera como um comando de depuração. Por exemplo, ele helpexibe todos os comandos possíveis com argumentos: A lista completa é bastante grande, mas veja, você pode enviar mensagens diretas ao Softune para qualquer tarefa! O que seria tão interessante enviar para lá ... Outra linha popular que é frequentemente procurada no firmware é . Vamos ver se temos um. Aparentemente, você pode despejar o firmware no cartão SD. Usando o link para a linha “Dumping files to card”, é fácil encontrar o código responsável por isso. Ele está localizado no gigantesco bloco Tarefa do Sistema (pid 11, como já sabemos) e é chamado pela mensagem sem argumentos. Dial em M240PTPTool , pressione Enter e olhar para a tela.

M240> help
********* debug command description ********

exposure request
Description: requests a release from Sub CPU
Parameter 1: Exposure Time TV

still request
Description: simulates the -still request- command flow of Sub CPU
Parameter: no

...

send Message;[Parameter1];[Parameter2];[Parameter2];...;...
Description: Sending Message to Task
Parameter 1: Receiver Task ID
Parameter 2: Command ID
Parameter 3: Command Data[0] (32 Bit)
Parameter 4: Command Data[1] (32 Bit)
Parameter 5: .
Parameter 6: .
use maximum 10 Parameter

...




dump

$ strings IMG_LOKI-212_1.1.0.2.bin | rg -i dump
GUI: HEX DUMP: Address: %x, Length: %d
HSK: DBG_WRITE_ROM_DUMP_SD: File was properly opened, but it seems to be empty.
ROM_DUMP
HSK: DBG_WRITE_ROM_DUMP_SD: Flushing Dump to ROM. Size %d
SD:\ROM_DUMP.bin
HSK: DBG_WRITE_ROM_DUMP_SD Command received!
ROM_DUMP.bin
HSK: DUMP failed, no cards inserted!
HSK: DUMP FlashROM to SD card.
HSK: DUMP FlashROM to CF card.
Dumping files to card


0x11080006

send Message;11;0x11080006



Em seguida, remova o cartão SD e verifique o que está nele.



Aqui está, um despejo completo, incluindo firmware.

Isso abre infinitas possibilidades. Por exemplo, você pode criar um pequeno dispositivo com um MCU, suporte a um host USB e botões para iniciar sequências complexas de mensagens ...

E então tivemos um segundo filho. :)

Epílogo


Se você não deseja quebrar o dispositivo, geralmente há uma maneira de examiná-lo sem abrir a caixa ou os fios de solda na placa de circuito. Abaixo estão minhas dicas, se você estiver interessado:

  • encontre todas as informações públicas sobre o dispositivo: especificações técnicas, dados sobre componentes, fotos do interior, vídeo da fábrica ;)
  • se você tiver firmware, mergulhe nele e procure dicas sobre saídas externas;
  • , ;
  • GND// , ;
  • ;
  • , ;
  • , (, );
  • , Google (USB/UART/SPI/I2C/1Wire);
  • , ;
  • , ;
  • , .



github.com/alexhude

!

Source: https://habr.com/ru/post/pt438168/


All Articles