Пишем прошивку для старого пин-пада

в 8:01, , рубрики: Без рубрики
Приветствую всех!

Многие из нас уже знают, что POS-terminal'ы и пин-пады обычно собираются на базе заказных чипов, даташиты на которые не найти. Но, понятное дело, так было далеко не всегда. И мне стало интересно: а что, если попробовать найти такой древний терминал, отреверсить его схему и написать что-то под него, не имея ни SDK, ни документации?

Пишем прошивку для старого пин-пада - 1

Итак, в сегодняшней статье разберём и разберёмся, как запустить раритетный пин-пад из начала двухтысячных годов. Попутно разберёмся с прошивкой старых защищённых микроконтроллеров и узнаем, как они работали. Традиционно будет много интересного.

Суть такова

Когда-то давно я уже писал пост про то, как работают пин-пады и что у них внутри.

Пишем прошивку для старого пин-пада - 2

Если разобрать типичный пин-пад, выпущенный после середины двухтысячных, то, скорее всего, все микросхемы внутри будут проприетарными. А это значит, что информация о них доступна, наверное, только самим разработчикам терминалов.

Но в лучшие годы всё было совершенно иначе. А как оно было, сейчас и будем разбираться.

Обзор оборудования

Пишем прошивку для старого пин-пада - 3

Так получилось, что в мои руки попал пин-пад Hypercom HFT106. Девайс очень старый, начала двухтысячных годов. По виду он тоже сильно отличается от привычных нам, напоминая то ли калькулятор, то ли какой-то сервисный прибор. Слот для смарт-карт расположен в задней части, карта вставляется вертикально.

Пишем прошивку для старого пин-пада - 4

Обратная сторона. Тут ничего интересного, только порт 6P6C.

Пишем прошивку для старого пин-пада - 5

А вот и пример терминала, к которому такой девайс подключался. Это Hypercom T7PS, древний аппарат на процессоре Z80. Но про этот экземпляр поговорим как-нибудь потом.

Внутренности

Само собой, чтобы узнать, на чём он собран, девайс надо разобрать.

Пишем прошивку для старого пин-пада - 6

Здесь это весьма проблематично — мало того, что он залит смолой, так ещё и к крышке приварена металлическая скоба, погруженная в эпоксидку. Из-за этого неразрушающая разборка невозможна. Крышку эту в итоге пришлось отломать.

Пишем прошивку для старого пин-пада - 7

Отковыряв крышку окончательно, видим отгороженную от остального пространства корпуса область, залитую смолой. В ней проглядывается батарейка, разумеется, давно севшая.

Пишем прошивку для старого пин-пада - 8

Дисплей, обычный 1602.

Пишем прошивку для старого пин-пада - 9

Пишем прошивку для старого пин-пада - 10

Модуль считывателя карт. В одном из разъёмов находилась SAM-карта, второй оказался пуст. Интересно, зачем он вообще, в залитом-то корпусе… На этой же плате находится концевик тампера.

Пишем прошивку для старого пин-пада - 11

SAM-карта. Обратная сторона маркировки не имела.

Что же внутри этого пин-пада?

Само собой, вопрос о том, на базе чего собрано данное устройство, так и остался открытым. Пришлось гуглить. На форуме nedoPC кто-то уже разбирал подобный терминал. Модель, правда, была другой, HFT105. После нескольких часов ковыряния эпоксидки и изучения фотографий платы было выяснено, что HFT106 является по сути более защищённым аналогом HFT105. По схемотехнике они абсолютно идентичны.

Пишем прошивку для старого пин-пада - 12

Плата терминала HFT105 крупным планом.

DS5002FP

Итак, пин-пад оказался собран на базе защищённого микроконтроллера от Dallas. Штука эта весьма интересная — по сути это 8051-совместимый МК, специально разработанный для подобных применений. У этого контроллера нет пользовательского ПЗУ, вся программа загружается в SRAM.

Пишем прошивку для старого пин-пада - 13

Вот его структурная схема. Видно, что для работы с внешней памятью все данные на шине тоже зашифрованы, а также обфусцированы (периодически МК читает из памяти случайные значения для защиты от сканирования шины логическим анализатором). Также имеется аппаратный вход тампера (Self-Destruct input), при активации которого сбрасываются ключи и векторы прерываний.

Для защиты от реверс-инжиниринга существовали доступные под заказ ещё более защищённые версии этого чипа, обладающие контуром безопасности прямо на кристалле, который защищает чип от вскрытия и исследований электронным микроскопом. В качестве алгоритма шифрования используется DES с ключом длиной в 64 бита, также по усмотрению заказчика мог быть предусмотрен проприетарный алгоритм шифрования. МК оборудован аппаратным генератором случайных чисел (если верить даташиту, принцип основан на девиациях частоты кварца и внутреннего генератора, которые измеряются контроллером), использующимся для генерации ключей.

Пишем прошивку для старого пин-пада - 14

Вот схема контура безопасности из даташита на МК. Как можно видеть, незашифрованные данные никогда не покидают защищённой зоны.
Ну что же, самое время разобраться, как же вообще работать с таким МК.

Софт

Итак, для того, чтобы написать какую-то прошивку, необходим SDK. Стандартный набор — библиотеки, компилятор и загрузчик.

Пишем прошивку для старого пин-пада - 15

SDK для столь экзотического контроллера без проблем можно найти: он имеется в составе Keil для МК MCS-51. Скачиваем Keil, открываем Device Database и устанавливаем поддержку для этого МК.

Теперь очередь заливки софта в контроллер. И тут всё весьма интересно: никакой программатор для этого не понадобится.

MTK2

Как ясно из описания МК, прошивка у него хранится в SRAM, которая сбрасывается при нарушении целостности контура. Логично, что загрузка прошивки должна осуществляться в уже собранное устройство.

Пишем прошивку для старого пин-пада - 16

Если отковырять одну из резиновых ножек, то можно увидеть там вырез, где скрываются два торчащих из смолы штырька. Один из них — земля, другой — PROG. Если их замкнуть, то при подаче питания будет запущен расположенный в масочном ПЗУ загрузчик, задача которого — поместить пришедшую по UART программу в SRAM. Перемычка на эти штырьки не налезала, поэтому я просто запихал туда фольгу от обёртки жвачки.

Пишем прошивку для старого пин-пада - 17

Теперь очередь софта для прошивки. Есть такая утилита как Dallas Microcontroller Toolkit (MTK2). Она предназначена для заливки HEX-файла с программой в целый модельный ряд МК от Dallas. Среди всех прочих есть и наш экземпляр.

Подключение

Пин-пад подключается к терминалу по интерфейсу RS-422. Внутри он реализован на базе двух трансиверов RS-485, один из которых включён всегда на приём, а другой — на передачу.

Пишем прошивку для старого пин-пада - 18

Само собой, чтобы подключить девайс к компьютеру, необходимо спаять переходник. Схема его в моём случае вышла такая:

Пишем прошивку для старого пин-пада - 19

Так получилось, что месяцем ранее я разобрал другой терминал — Hypercom Optimum T4220. Именно из его интерфейсного модуля и были позаимствованы все нужные компоненты — микросхема, разъём 6P6C и кабель от пин-пада. В принципе, ничто не мешает использовать два трансивера RS-485, как это реализовано в пин-паде.

Схемы девайса с форума nedoPC. Скопировал сюда на всякий случай

Пишем прошивку для старого пин-пада - 20

Пишем прошивку для старого пин-пада - 21

Пишем прошивку для старого пин-пада - 22

Пишем прошивку для старого пин-пада - 23

Первый запуск

Итак, подключаем девайс к компьютеру. В качестве преобразователя USB-UART выступила традиционно Arduino. Замыкаем контакты и подаём питание.

Пишем прошивку для старого пин-пада - 24

Теперь открываем MTK2 и пытаемся установить соединение с загрузчиком. И оно работает!
Само собой, если подать питание просто так, то ничего не будет — из-за севшей батарейки оригинальная прошивка давно утрачена.

Загрузчик

Пишем прошивку для старого пин-пада - 25

Если открыть список команд, то можно заметить, что среди них есть возможность прямо из загрузчика управлять портами. Для проверки попробуем завести пищалку. При помощи команды P выставляем высокий уровень на соответствующей ножке, и терминал начинает непрерывно пищать. Ну что же, схема нас не обманула, HFT106 действительно во многом близок к HFT105.

Официальный порядок загрузки прошивки такой:

  1. F. Затереть SRAM.
  2. L. Залить HEX.
  3. D. Прочитать память.
  4. V. Проверить правильность записи.
  5. C. Сверить CRC.

В ходе выполнения этих операций происходит очистка памяти, после чего ГСЧ генерирует ключ (он является неизвлекаемым и недоступен для чтения), которым шифруется прошивка. Если выполнение программы загрузчика при этом не было прервано (то есть если не была выполнена команда E или если МК не был сброшен), то возможно и чтение содержимого ОЗУ, что используется для верификации.

После того, как программа успешно залита, необходимо установить командой Z флаг защиты, блокирующий доступ к памяти. Отныне её содержимое будет закрыто навсегда, загрузчик или нечто другое извне получить доступ к нему не сможет. Операция эта необратима, если данный бит взведён, то обнулить его можно либо полной очисткой памяти, либо командой U, которая сбрасывает ключи (что тоже приводит к потере информации).

Пишем первую программу

Ну что же, время написать что-то под этот девайс. Начнём, конечно, с классического микроконтроллерного «Hello, world!» — с вывода текста на экран.
Дисплей здесь работает в восьмибитном режиме, все его линии данных подключены к порту P2. Для управляющих линий отведён P3. Итак, тестовая прога получилась вот такая:

#include <REG52.H>                /* special function register declarations   */
                                  /* for the intended 8051 derivative         */
#include <stdio.h>                /* prototype declarations for I/O functions */


#ifdef MONITOR51                         /* Debugging with Monitor-51 needs   */
char code reserve [3] _at_ 0x23;         /* space for serial interrupt if     */
#endif                                   /* Stop Exection with Serial Intr.   */
                                         /* is enabled                        */

/*------------------------------------------------
The main C function.  Program execution starts
here after stack initialization.
------------------------------------------------*/
void delay(void) {
unsigned long n;
	for(n = 0; n < 100; n++);;
}

void lcdSend(int isCommand, unsigned char toLCD) {
	P3 &= ~(1 << 7);
    if(isCommand == 0) P3 |= (1 << 6);
	else if(isCommand == 1) P3 &= ~(1 << 6);
    delay();
	P2 = toLCD;
	P3 |= (1 << 5);
	delay();
	P3 &= ~(1 << 5);
	delay();
}
void lcdCommand(unsigned char cmd) {
    lcdSend(1, cmd);
}

void lcdChar(const char chr) {
    lcdSend(0, chr);
}

void lcdString(const char* str) {
    while(*str != '') {
        lcdChar(*str);
        str++;
    }
}
void main (void) {
/*------------------------------------------------
Setup the serial port for 1200 baud at 16MHz.
------------------------------------------------*/
#ifndef MONITOR51
    SCON  = 0x50;		        /* SCON: mode 1, 8-bit UART, enable rcvr      */
    TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */
    TH1   = 221;                /* TH1:  reload value for 1200 baud @ 16MHz   */
    TR1   = 1;                  /* TR1:  timer 1 run                          */
    TI    = 1;                  /* TI:   set TI to send first char of UART    */
#endif

   lcdCommand(0x38);
   lcdCommand(0x01);
   lcdCommand(0x06);
   lcdCommand(0x0C);
   lcdCommand(0x80); 
   lcdString("Hello, Habr!");
	while(1);;
}


Инициализация дисплея абсолютно стандартная, подробно расписывать её не вижу смысла.
Собираем проект и в папке с ним получаем *.hex-файл с готовой прошивкой.

Пишем прошивку для старого пин-пада - 26

Теперь открываем MTK2, выбираем в меню «Load SRAM», выбираем нашу прошивку. По окончании загрузки отправляем команду E.
И, если всё было успешно, на экране загорится примерно следующее:

Пишем прошивку для старого пин-пада - 27

Ну что же, всё успешно.

Клавиатура

Ну, где дисплей, там и клавиатура. Схемы считывателя смарт-карт у меня нет, так что это единственная периферия, которую ещё можно запустить. И программа оказалась такой:

#include <REG52.H>                /* special function register declarations   */
                                  /* for the intended 8051 derivative         */
#include <stdio.h>                /* prototype declarations for I/O functions */

#ifdef MONITOR51                         /* Debugging with Monitor-51 needs   */
char code reserve [3] _at_ 0x23;         /* space for serial interrupt if     */
#endif                                   /* Stop Exection with Serial Intr.   */
                                         /* is enabled                        */

/*------------------------------------------------
The main C function.  Program execution starts
here after stack initialization.
------------------------------------------------*/
void delay(void) {
unsigned long n;
	for(n = 0; n < 100; n++);;
}
char s[16];
char symbols[4][4] = {{'E', '0', 'R', 'C'},
   	              {'9', '8', '7', 'B'},
		      {'6', '5', '4', 'A'},
		      {'3', '2', '1', 'Z'}};
char symbolsP0[4] =  {'L', 'K', 'J', 'I'};
void lcdSend(int isCommand, unsigned char toLCD) {
	P3 &= ~(1 << 7);
    if(isCommand == 0) P3 |= (1 << 6);
	else if(isCommand == 1) P3 &= ~(1 << 6);
    delay();
	P2 = toLCD;
	P3 |= (1 << 5);
	delay();
	P3 &= ~(1 << 5);
	delay();
}
void lcdCommand(unsigned char cmd) {
    lcdSend(1, cmd);
}

void lcdChar(const char chr) {
    lcdSend(0, chr);
}

void lcdString(const char* str) {
   while(*str != '') { //*str != ''
        lcdChar(*str);
        str++;
    }
}
void main (void) {
   int n1, i, j, k;  
   lcdCommand(0x38);
   lcdCommand(0x01);
   lcdCommand(0x06);
   lcdCommand(0x0C);
	while(1) {
		P1 = 0x0F;
		P0 |= (1 << 7);
		for(i = 4; i < 8; i++) {
		for(j = 4; j < 8; j++) P1 |= (1 << j);
		P1 &= ~(1 << i);
		for(k = 0; k < 4; k++) {
			if(((P1 >> k) & 1) == 0 ) {
				P3 &= ~(1 << 4);
				n1 = P1;
				sprintf(s, "%X", n1);
				lcdCommand(0x80); 
				lcdString("Scanc0de: ");
				lcdString(s);
				lcdCommand(0xC0);
				lcdString("Key: ");
				lcdChar(symbols[i-4][k]);
				for(j = 0; j < 30; j++)	delay();
			}
			else {
				P3 |= (1 << 4);
			}
		}
	}
		P0 &= ~(1 << 7);
		for(i = 0; i < 4; i++) {
			if(((P1 >> i) & 1) == 0 ) {
				P3 &= ~(1 << 4);
				n1 = P1;
				sprintf(s, "%X", n1);
				lcdCommand(0x80); 
				lcdString("Scanc0de: ");
				lcdString(s);
				lcdCommand(0xC0);
				lcdString("Key: ");
				lcdChar(symbolsP0[i]);
				for(j = 0; j < 30; j++)	delay();
			}
			else {
				P3 |= (1 << 4);
			}
	}
}
}

Запускаем, и вот результат:

Пишем прошивку для старого пин-пада - 28

А что же насчёт банковских функций?

Увы, у меня нет никакого софта или документации на пин-пады или терминалы Hypercom. Пожалуй, по этим терминалам информации в интернете меньше всего.
Что же до платёжных функций (хранения ключей, работы с картами), то аппаратной их поддержки в микроконтроллере нет. DS5002FP был чипом общего назначения (и предназначался, к слову, не только для платёжных терминалов, но и для тех областей, где была нужна защита от реверс-инжиниринга), так что всё было реализовано средствами почившей прошивки.

Пишем прошивку для старого пин-пада - 29

Из других терминалов, работавших на базе такого чипа, мне известен Castles CIT7000, для которого я даже смог найти SDK. Увы, самой железки у меня нет.

Вот как-то так

Увы, сейчас реально применить для чего-то девайс не представляется возможным: батарейка давно села, а поменять её, не разрушив корпус, не представляется возможным. По сути срок жизни девайса ограничен зарядом батарейки, после исчерпания которого прошивка держится в памяти только до выключения питания. Тем не менее, было очень интересно попробовать запустить этот раритетный экземпляр.
Такие дела.

Ссылки


Возможно, захочется почитать и это:

Пишем прошивку для старого пин-пада - 30

Автор: Лев

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js