HENRY

De Garoa Hacker Clube
Ir para navegação Ir para pesquisar

Esta página documenta a máquina impressora de cheques HENRY, encontrada no lixo da Estação de Metareciclagem Samambaia (Distrito Federal).

Modelo da PCB: HENRY PINHAIS/PR REV.1

componentes

  • CPU: 80C31
  • RAM: UM62256B (RAM estática de 32k bytes)
  • EEPROM 27C512 (64k bytes) Marcada com um adesivo escrito "PROT V19 Henry Equipamentos e Sistemas LTDA"
  • glue logic: diversos chips TTL da família 74
  • display de cristal líquido de 2x16 caracteres (HD44780)
  • CHIP desconhecido na posição U2.

U2

  • hipótese: DS1307: 64 x 8 Serial Real-Time Clock

esquemático

Está sendo levantado o esquemático desta placa (rev1) no repositório https://github.com/GaroaHC/HENRY no subdiretório kicad.

emulação

No repositório https://github.com/GaroaHC/HENRY no subdiretório mess há um esboço de emulador deste equipamento (já parcialmente funcional).

Comportamento do dispositivo real

  • Ao ligar, aparece a mensagem "Inicializando..."
  • Logo depois, "Verificando memória..."
  • E, enfim, "Ajuste a data:\n01/01/99 sex"
  • botão preto superior muda de campo ciclicamente da esquerda para a direita
  • botão preto inferior incrementa o campo selecionado (o dia da semana é calculado pela máquina e exibido à direita da data)
  • botão azul alterna entre ajuste de data e a mensagem "PROT Vrs. R19\n 01/02/02" o que nos leva a crer que o firmware R19 é de 1.o de fevereiro de 2002.
  • botão azul pressionado por algum tempo = OK, vai para próxima configuração: "Ajuste a hora" "01:14:00"
  • botão azul pressionado por algum tempo = mostra "Entrando em ajustes." e logo depois "Apagar a memoria e o horario ?" + cursor piscante
  • clique no botao azul = "PROTOC. A" "01:01 seg 1via"
  • Ao fechar o opto de detecção de papel, a cabeça de impressão se move para a direita e depois para a esquerda e em seguida, vemos a mensagem "Dificuldades :" "Movimento motor"

ligações

display

Display LCD de 2 linhas de caracteres compatível com HITACHI HD44780. Extremamente comum.

  • Pino 1 = marrom -> ligado ao pino 1 do display
  • pino 2 = não usado
  • pino 3 = vermelho
  • e assim por diante

Os pinos 15 e 16 do display não estão ligados a nada. Apesar de se pular o pino 2 no conector, a ligação dos pinos do display é sequencial, ou seja, pino 1 = marrom, pino 2 = vermelho, etc...

teclado

  • pino 1 = marrom -> botão preto de cima
  • pino 2 não usado
  • pino 3 = vermelho -> botão preto de baixo
  • pino 4 = laranja -> botão azul
  • pino 5 = amarelo -> GND: comum a todos os botões

motores

  • pino 1 = amarelo
  • pino 2 não usado
  • pino 3 = laranja
  • pino 4 não usado

impressora

  • pino 1 não usado
  • pino 2 = amarelo
  • pino 11 = roxo

jumper 1

Botão liga-desliga ? Aparentemente não tem polaridade.

Olhando para o silk da placa com o texto JP1 de pé:

  • pino da esquerda = marrom
  • pino da direita = vermelho

sensores

  • pino 1 não usado (o conector nem encaixa nesse pino)
  • pino 2 = marrom (Vcc) pino 0 dum sensor optico (de leitura da presença de um cheque?)
  • pino 3 não usado
  • pino 4 = vermelho -> pino 1 do opto do encoder
  • pino 5 = laranja -> pino 3 do opto do encoder
  • pino 6 = amarelo -> pino 1 do fim de curso
  • pino 7 = verde -> pino 3 do fim de curso
  • pino 8 = azul -> pino 1 do sensor de cheque
  • pino 9 = roxo -> pino 3 do sensor de cheque

Os pino 2 tanto do sensor do cheque e do fim de curso não é usado.

borne CN7

Olhando o silk com o texto GND, VAC, etc de pé:

  • GND -> BAT - da placa da fonte
  • VAC da esquerda -> BAT + da placa da fonte
  • VAC da direita -> não está ligado em nada
  • BAT + -> fio vermelho do soleníde
  • BAT - -> aterramento (na carcaça e na fiação da tomada)


borne CN8

  • C -> ligado em nada
  • NA -> fio preto do solenóide

dump da EEPROM

codigo de arduino para fazer o dump

Rodamos esse código 4 vezes (uma para cada par de bits) e o resultado foram 4 arquivos de dump lidos na porta serial.

#define dado0 A0
#define dado1 A1
#define Addr0 2
#define Addr1 3
#define Addr2 4
#define Addr3 5
#define Addr4 6
#define Addr5 7
#define Addr6 8
#define Addr7 9
#define Addr8 10
#define Addr9 11
#define Addr10 12
#define Addr11 13
#define Addr12 A2
#define Addr13 A3
#define Addr14 A4
#define Addr15 A5

int endereco;

void setup(){
  endereco = 0;
  Serial.begin(9600);
  pinMode(Addr0, OUTPUT);
  pinMode(Addr1, OUTPUT);
  pinMode(Addr2, OUTPUT);
  pinMode(Addr3, OUTPUT);
  pinMode(Addr4, OUTPUT);
  pinMode(Addr5, OUTPUT);
  pinMode(Addr6, OUTPUT);
  pinMode(Addr7, OUTPUT);
  pinMode(Addr8, OUTPUT);
  pinMode(Addr9, OUTPUT);
  pinMode(Addr10, OUTPUT);
  pinMode(Addr11, OUTPUT);
  pinMode(Addr12, OUTPUT);
  pinMode(Addr13, OUTPUT);
  pinMode(Addr14, OUTPUT);
  pinMode(Addr15, OUTPUT);
  
  pinMode(dado0, INPUT);
  pinMode(dado1, INPUT);
}

void le_dado(int address){
  digitalWrite(Addr0, address & (1 << 0) ? HIGH : LOW);
  digitalWrite(Addr1, address & (1 << 1) ? HIGH : LOW);
  digitalWrite(Addr2, address & (1 << 2) ? HIGH : LOW);
  digitalWrite(Addr3, address & (1 << 3) ? HIGH : LOW);
  digitalWrite(Addr4, address & (1 << 4) ? HIGH : LOW);
  digitalWrite(Addr5, address & (1 << 5) ? HIGH : LOW);
  digitalWrite(Addr6, address & (1 << 6) ? HIGH : LOW);
  digitalWrite(Addr7, address & (1 << 7) ? HIGH : LOW);
  digitalWrite(Addr8, address & (1 << 8) ? HIGH : LOW);
  digitalWrite(Addr9, address & (1 << 9) ? HIGH : LOW);
  digitalWrite(Addr10, address & (1 << 10) ? HIGH : LOW);
  digitalWrite(Addr11, address & (1 << 11) ? HIGH : LOW);
  digitalWrite(Addr12, address & (1 << 12) ? HIGH : LOW);
  digitalWrite(Addr13, address & (1 << 13) ? HIGH : LOW);
  digitalWrite(Addr14, address & (1 << 14) ? HIGH : LOW);
  digitalWrite(Addr15, address & (1 << 15) ? HIGH : LOW);

//  delay(1);
  
  Serial.write(digitalRead(dado1) ? "1" : "0");
  Serial.write(digitalRead(dado0) ? "1" : "0");
}

void loop(){
  if (endereco<65536){
    Serial.print((endereco >> 8) & 0xff, HEX);
    Serial.print(endereco & 0xff, HEX);
    Serial.write(":");
    le_dado(endereco);
    Serial.write("\n");
    endereco++;
  }
}

script python para gerar a imagem

Depois de executar o comando

cut -d: -f2 dump0.txt > bits0.txt
cut -d: -f2 dump1.txt > bits1.txt
cut -d: -f2 dump2.txt > bits2.txt
cut -d: -f2 dump3.txt > bits3.txt

Usamos o script python abaixo para unir os dumps de pares de bits em uma única imagem dump.bin de 64kbytes:

b0 = open("bits0.txt").readlines()
b1 = open("bits1.txt").readlines()
b2 = open("bits2.txt").readlines()
b3 = open("bits3.txt").readlines()

dump = open("dump2.bin", "wb")

for i in range(0x100, 65536):
  valor = b3[i].strip() + b2[i].strip() + b1[i].strip() + b0[i].strip()
  print valor
  print int(valor, 2)
  dump.write(chr(int(valor,2)))

script para desembaralhar endereços

As 4 vias menos significativas do barramento de endereços estão embaralhadas.

Para gerar uma ROM desembaralhada, usamos o seguinte script:

b0 = open("bits0.txt").readlines()
b1 = open("bits1.txt").readlines()
b2 = open("bits2.txt").readlines()
b3 = open("bits3.txt").readlines()

dump = open("henry_protv19.bin", "wb")
desobfuscado = open("henry_protv19_desobfuscado.bin", "wb")

swap_rule = [7, 6, 5, 4, 0, 1, 2, 3]

for addr in range(65536):
  i = addr
  value_str = b3[i].strip() + b2[i].strip() + b1[i].strip() + b0[i].strip()
  value = int(value_str, 2)
  dump.write(chr(value))

  swapped_addr = addr & 0xff00
  for i in range(8):
    swapped_addr |= ((addr>>i) & 1) << swap_rule[i]

  i = swapped_addr
  value_str = b3[i].strip() + b2[i].strip() + b1[i].strip() + b0[i].strip()
  value = int(value_str, 2)
  desobfuscado.write(chr(value))

dump.close()
desobfuscado.close()