Механізм захисту від клонування адаптерів XELTEK

Передмова

Ця історія почалася з того, що нам якось знадобилося прочитати/записати мікросхему FLASH пам'яті типу SPANSION S29GL512 в корпусі TSOP56. До цього часу ми успішно експлуатували програматор XELTEK SuperPro 500P. Але, на жаль, встановлена в ньому сокета з 48-ма контактами не дозволяла цього зробити навіть із застосуванням перехідника. Само собою, що і в програмі на PC для цього програматора підтримка таких мікросхем була відсутня.

Пора оновлюватися, вирішили ми, і набули (не вважайте за рекламу) програматор того ж виробника моделі SuperPro 6100, в якому використовуються змінні адаптери з різними сокетами. Також окремо було придбано необхідний, як нам тоді здавалося, адаптер моделі CX1011 з сокетой TSOP56 (в комплекті з програматором йшов адаптер з сокетой ZIF48).


Умовимося надалі називати програму програматора просто софтом, тому що «програма програматора» звучить не дуже естетично.

Після отримання всього цього ми зібрали конструктор з програматора з адаптером і спробували почати з ним роботу.



Але після того, як в софті була потрібна вибрана мікросхема, програматор кілька разів пропищав і на його дисплеї відобразилася загадковий напис «ERROR CODE: 1D». Софт теж вилаявся повідомленням, що даний адаптер для програмування цієї мікросхеми не підходить. Як же так!? Адаптер з програматором щасливо одружилися, мікросхема з сокетой теж, а ось злісний виробник вирішив, що цього недостатньо, і користувач, в додаток до нового програматора, неодмінно повинен придбати ще й «новий» адаптер DX1011. За який, до речі, на сайті виробника хочуть близько трьохсот вічнозелених. Ну да ладно, в нашому випадку ми його купили помилково, хоча купувати «новий» ніякого бажання все ж не було. Але ж у когось він міг зберегтися від старого програматора, а хтось, можливо, захотів би виготовити його самостійно. Так що саме для цієї аудиторії дана стаття.

При підготовці цього матеріалу ми не ставили за мету навчити читача користуватися різними програмами і апаратними пристроями, якими довелося скористатися на цьому шляху. Тому не будемо засмічувати статтю описом тонкощів роботи з усім цим інструментарієм, залишивши його за кадром. Але якщо комусь будуть цікаві подробиці — з задоволенням постараємося їх прокоментувати.

Тут в самий раз привести текст відмови про відповідальність, сенс якого полягає в тому, що автор не несе ніякої відповідальності за будь-яке використання вами матеріалів даній статті. Іншими словами — тільки ви самі будете відповідати за свої дії, на які вас може спонукати ознайомлення з цим матеріалом.

Попереднє обстеження
Огляд адаптера дозволив виявити на ньому восьминогую мікросхему з написом AE801, документація на яку в інтернеті, природно, була відсутня. Ця мікросхема добре видно у правому куті фотографії адаптера CX1011 вище.

Хоча деяку інформацію про цю мікросхемі все ж таки вдалося знайти. На сайті XELTEK в розділі FAQ у відповіді на питання: «Яка різниця між програматорами SuperPro 6000 і 6100?» присутній цікава фраза: «Адаптери серії CX (для програматорів 6000) і DX (для програматорів 6100) абсолютно однакові, за винятком ID чіпа, який адаптери серії DX використовує вдосконалену захист.» Стало ясно, що ця мікросхема — якийсь ID чіп, який використовується програматором для ідентифікації встановленого в нього адаптера. Ось тільки про яку захист йдеться: від кого або від чого потрібно захищати адаптер? Ну звичайно ж від нас з вами!

Ця захист подібна до тієї, яка зараз повсюдно використовується в картриджах для принтерів, щоб їх не заправляли повторно, а купували нові. Але тут ситуація дещо інша. Ви на свої кровні купуєте недешевий адаптер і сподіваєтеся, що будете користуватися ним вічно. Не тут-то було! Виробник про це завбачливо подбав і, уподібнившись самому Творцеві, вирішив штучно обмежити адаптера термін його тлінній життя. На підтвердження чого, в софті виявляються такі багатозначні повідомлення:

— «Socket adapter end-of-life is near. Please prepare to replace with a new one.»
— «Adaptor usage beyond its life cycle, please change.»

Як вам подобається цей перл: «Термін життя адаптера підходить до кінця»? І особливо фраза «replace with a new one», так пестить слух відділу продажів.

Чомусь на сайті XELTEK на сторінці з адаптерами про їх тлінність — ні слова! Перефразовуючи одну відому приказку про козу і баян так і хочеться сказати: «А нафіга адаптера захист»?

Але як би те ні було, потреба все ж таки прочитати/записати мікросхему FLASH пам'яті (про що, треба сказати, ми вже забули, захопившись всім іншим) і непереборне бажання у що б то не стало полегшити долю нещасного, приреченого на неминучу загибель «хворого» адаптера, змусило нас рухатися далі.

Підготовка до лікування
Умовимося надалі називати PC, на якому працює софт для програматора — хостом.

Для обміну даними між хостом і програматором використовується інтерфейс USB, а в ньому кілька USB каналів (Pipes). По одному з USB каналів хост посилає в програматор команди, по іншому шле в нього дані з наступного отримує дані з програматора.
Потрібно було ідентифікувати інтерфейс для обміну даними між AE801 і самим програматором. Тут виробник не став мудрувати, використавши старий добрий UART зі швидкістю близько 10500 бод. У мікросхеми AE801, яка по суті є восьминогим мікроконтролером, ніжки 1 і 4 з'єднані з «землею», на ніжку 8 подається живлення +5V, ніжка 3 використовується для двонаправленої передачі даних по UART, ніжка 7 використовується, як позитивний CS, а на ніжку 6, одночасно з появою одиниці на ніжці 7 подається тактову частоту 4 Мгц. З відомих нам мікроконтролерів про восьми ногах для даної розпіновки найкраще підходить ATMEL серій ATtiny25, 45, 85. Правда, використовуваний для них корпус SOIC8 дещо ширше, ніж потрібно.

При дослідженні обміну даними між AE801 на адаптері і програматором з'ясувалася одна цікава річ: при виборі будь-якої мікросхеми в софті, ще до того, як відбудеться вибір мікросхеми AE801 на адаптері, на її ніжці 3 з'являються якісь пакети даних. Виходило, що є ще до початку спілкування з мікросхемою з адаптера програматор спілкується ще з кимось. Надалі виявилося, що в самому програматорі встановлена така ж мікросхема AE801, що сидить на тій же двобічної шині даних, що і AE801 з адаптера. І вона служить тим же цілям — захист від клонування, але тепер вже самого програматора.

Далі софт на хості був модифікований, щоб зберігати в лог файл процедуру обміну даними між ним і програматором. З отриманого лода стало абсолютно зрозуміло, що нічого не зрозуміло. Обмін даними був якимось чином зашифрований і зашумлений сміттям. Мабуть в цьому і полягало те саме «удосконалення захисту». Але одне стало очевидним — адаптер повідомляє програматору назву своєї моделі прямо в текстовому вигляді і свій вік, щоб можна було своєчасно відправити його на заслужений, на думку XELTEK, відпочинок. Все інше — сміття.

Шляхом подальшого вивчення з'ясувалося, що алгоритм захисту писав людина дуже далекий від цієї теми. Так звана «вдосконалена захист» не витримує ніякої критики.
Однак, в лоб в балці розібратися не вдалося і стало очевидним, що тепер доведеться переміщатися всередину самого програматора. Його електронна начинка виглядає, як листковий пиріг, у вигляді безлічі окремих плат, з'єднаних разом стійками і роз'ємами.


Одна з цих плат (назвемо її, за аналогією з PC, «материнської») містить ARM мікроконтролер ATMEL AT91SAM9G20, SDRAM, SPI FLASH з прошивкою, той самий ID чіп AE801 з моделлю програматора та його серійним номером, мікросхему контролера USB і ряд інших мікросхем.


Ще на одній платі встановлена мікросхема XILINX, яка разом з іншими платами з транзисторними збірками управляє ніжками мікросхеми на підключеному до програматора адаптері під час процедур читання/запису і т. д.


Вся прошивка ARM мікроконтролера міститься у зовнішній мікросхемі SPI FLASH, що, звичайно ж, теж ніяк не сприяє посиленню захисту. Зазвичай завантажувач ховають у внутрішній пам'яті мікроконтролера, недоступною для читання, а прошивки або оновлення розміщуються зовні, шифрують. Але розробники з XELTEK вирішили піти іншим шляхом, заморочившись з власницькими чіпами AE801, залишивши прошивку ARM-а на розтерзання. Чим ми, власне, і зайнялися далі.

Ідея полягала в тому, щоб розбирати «usb» файл алгоритму програматора і потім зібрати проект в одній з ARM IDE, щоб потім через JTAG, маючи исходник на асемблері, вивчати роботу програматора в частині його спілкування з мікросхемою AE801.

На материнській платі вельми до речі було передбачено місце під роз'єм JTAG. Для зручності відладки роз'єм для підключення JTAG був змонтований на боці пластикового корпусу програматора і з'єднаний з материнською платою плоским шлейфом.


В результаті вийшов такий собі Development Kit.


Так як у нас був JTAG OLIMEX ARM-USB-OCD, що зберігся від якогось старого проекту, вибір ARM IDE упав на IAR Embedded Workbench, тому що в ньому підтримується налагодження через GDB сервер. Втім, налаштування цього самого GDB сервера виявилася завданням досить заплутаною. І на те, щоб зібраний в результаті асемблерного исходника проект почав завантажуватися в SDRAM програматора і з'явилася можливість налагодження, довелося витратити якийсь час.

Після того, як всі нарешті запрацювало з під відладчика, деякі самі «цікаві» методи алгоритму були переписані, щоб у них було зручніше розбиратися. Таким чином, поступово вдалося накопичити інформацію, що дозволила розібратися в механізмі роботи програматора, який описаний нижче в дещо спрощеному вигляді.

При включенні живлення програматора, ARM мікроконтролері починає роботу його вбудований завантажувач (умовно нульовий), який завантажує з SPI FLASH інший завантажувач (назвемо його першим) у своє внутрішнє ОЗУ, ремапит це ОЗП на адресу 0 і передає керування першому завантажувачу. Почавши роботу, перший завантажувач налаштовує на ARM-е SDRAM контролер, підключаючи таким чином зовнішнє ОЗП за адресою 0x20000000 і переписує туди інший завантажувач (назвемо його другим) з тієї ж SPI FLASH і передає йому управління. Другий завантажувач налаштовує зовнішню мікросхему контролера USB для спілкування з хостом, виводить на LCD екранчик рядка з назвою програматора і версією прошивки, спілкується зі своїм власним ID чіпом AE801 і в результаті потрапляє в цикл обробки команд від хоста.

Для роботи з кожним типом мікросхем пам'яті створена своя прошивка для ARM мікроконтролера, називається алгоритмом. Файли алгоритмів мають розширення «usb» і зберігаються на хості в каталозі «algoX» з встановленою програмою. В каталозі «бібліотека» знаходяться прошивки для мікросхеми XILINX і файли з розширенням «wls», в яких міститься інформація про відповідність потрібного алгоритму кожній, підтримуваної програматором мікросхемі, тип необхідного для цієї мікросхеми адаптера, а також деякі додаткові параметри для кожної мікросхеми. Наприклад, напруга живлення, напруги програмування і т. п.

Після того, як в софті буде обрана якась мікросхема, необхідно переконатися, що в програматор встановлений відповідний адаптер. Для цього хост посилає в програматор команду — запит типу встановленого в ньому адаптера. Програматор запитує мікросхеми AE801 з адаптера його тип і спеціальним чином сформований відправляє відповідь назад на хост. Софт на хості порівнює тип адаптера з файлу «wls» з типом адаптера з відповіді і в разі їх збігу відправляє в програматор за адресою 0x20020000 черговий завантажувач (назвемо його третім) — файл «loader.bin», що знаходиться в каталозі «bin». Після передачі управління третьому завантажувачу хост з його допомогою завантажує за адресою 0x20000000 відповідний даному типу мікросхеми алгоритм (файл «usb»), прошивку для XILINX і в підсумку передає управління завантажений алгоритмом. Після деяких налаштувань заліза алгоритм, в свою чергу, знову потрапляє в цикл обробки команд від хоста. Проміжний третій завантажувач потрібен тільки для того, щоб робочий алгоритм кожен раз вантажився по одному і тому ж адресою 0x20000000.

При виборі в софті інший мікросхеми вся описана вище процедура повторюється, починаючи з запиту хостом типу встановленого в програматор адаптера.

Після того, як завантажений в програматор алгоритм переходить у цикл обробки команд від хоста, всі подальші дії активізуються тільки цими командами. Іншими словами, хост стає ведучим, а програматор веденим пристроєм. Мікросхема ж AE801 з адаптера є підлеглою по відношенню до програматора і після подачі на її ніжку 7 (CS) активного високого рівня, а на ніжку 6 тактової частоти 4 MHz також переходить у цикл обробки команд від програматора. Ніжка 3 мікросхеми AE801 спочатку налаштовується на прийом команд від програматора. Після відправки чергової команди, програматор налаштовує лінію даних на прийом, а AE801, відповідно, свою ніжку 3 на передачу і відправляє дані програматора. Таким чином відбувається обмін даними між AE801 в адаптері і програматором. Обмін даними між внутрішньою AE801 на материнській платі і програматором відбувається точно таким же чином.

Лікування
Отже, ми безпосередньо підійшли до розгляду механізму захисту адаптерів серії DX.

Як згадувалося раніше, щоб не перевантажувати статтю зайвими подробицями, наведемо тут лише квінтесенцію пройденого шляху — опис процесу обміну даними між програматором і ID чіпом AE801.

Термінологія, використовувана в даному описі:

  • Термін «ніжка» відноситься до відповідних висновків мікросхеми AE801.
  • Рахунок байт — починаючи з одиниці.

  • Кожен раз, програматор, відправивши в мікросхему певну кількість байт, переводить лінію даних на прийом, а мікросхема, отримавши ці дані, перемикає ніжку 3 на передачу і т. д. Тому опис цих перемикань і згадка ніжки 3 наводитися не будуть.
  • Розповідь ведеться від особи мікросхеми AE801.

1. При наявності на ніжці 7 неактивного низького рівня, ніжка 3 налаштована на введення і ми знаходимося або в скиданні, або в стані сну.

2. Коли програматор подасть на ніжку 7 активний високий рівень (на ніжку 6 при цьому подається тактова частота 4 MHz), ми повинні передати у програматор 6 випадкових байт.

Відомо, що для використання алгоритму генерації випадкових, а точніше псевдовипадкових чисел із стандартної бібліотеки З спершу необхідно викликати команду srand(), передавши їй у якості вхідного аргументу якесь число — сіль, використовуючи яку кожен виклик команди rand() повертатиме наступне значення з визначеною цим числом псевдовипадковою послідовності. В PC в якості джерела ентропії для srand() зазвичай використовується time(), але в простих мікроконтролерах, як правило, немає годинника реального часу і цю задачу можна вирішити, наприклад, зберігаючи кожен раз після скидання нове значення для srand() в EEPROM. Швидше за все, саме так це й було реалізовано в AE801. За великим рахунком, нам взагалі немає потреби генерувати випадкові числа, але рішення цієї задачі здалося цікавим.

Ми реалізували прототип AE801 на мікроконтролері фірми Microchip (в той момент він просто опинився під рукою), який працював від свого власного внутрішнього генератора на частоті 8 Мгц і по відношенню до нього зовнішня частота 4 MHz, яка надходить на ніжку 6, виявилася прийнятним (і, мабуть, єдиним) джерелом ентропії.

Ніжка 6 у програмі використовувалася, як цифровий вхід і з неї в циклі начитывалось 16 біт, необхідних для передачі в метод srand().


3. Отримуємо з програматора 9 байт і підтверджуємо їх отримання відправкою в програматор отриманого шостим байти.

4. Отримуємо з програматора 5 байт. Перший з отриманих п'яти байт відправляємо в програматор як є, а решта 4-е шифруємо за алгоритмом RSA в 4-х 16-бітних слова і надсилає отримані 8 байт в програматор. Причому, для кожного з отриманих після шифрування слів спочатку відправляється старший байт, а потім молодший. На завершення, ще раз відправляємо в програматор перший з отриманих п'яти байт. Разом 10 байт.

В якості алгоритму шифрування використаний RSA з дуже короткими ключами 63, 847 і 2773. Кому цікаво, можуть знайти інформацію про це, наприклад, ТУТ.

У прошивці алгоритму для обчислення RSA використовується цикл з 2773-х ітерацій. Але так як вхідним числом для шифрування є байт, а вихідним — слово з двох байт, для спрощення обчислення RSA була сформована таблиця з 256-і слів, що зайняло зайвих 512 байт програмної пам'яті.

Таблиця RSA
{
0x0000, 0x0001, 0x03d0, 0x0640, 0x059d, 0x045f, 0x0191, 0x020b, 0x0863, 0x0209, 0x0933, 0x0489, 0x017f, 0x0168, 0x00d8, 0x0717,
0x0741, 0x0315, 0x040d, 0x0368, 0x0984, 0x084f, 0x06d8, 0x0832, 0x08b2, 0x0602, 0x07aa, 0x06a4, 0x0044, 0x086f, 0x08da, 0x07cd,
0x067f, 0x099f, 0x0797, 0x0086, 0x0ab4, 0x0088, 0x09e6, 0x07c5, 0x0433, 0x082a, 0x06d4, 0x00d0, 0x06f8, 0x029d, 0x0496, 0x04f5,
0x0525, 0x06ef, 0x037f, 0x02ad, 0x0606, 0x0133, 0x03b2, 0x0573, 0x0a1d, 0x017d, 0x09ad, 0x0674, 0x05ff, 0x0745, 0x097a, 0x02d9,
0x0373, 0x02f3, 0x09a6, 0x0402, 0x0969, 0x05be, 0x01c5, 0x0ab7, 0x042c, 0x074c, 0x0965, 0x047d, 0x0989, 0x0a81, 0x00a4, 0x00fd,
0x03ee, 0x099c, 0x0695, 0x05ee, 0x028d, 0x0435, 0x0243, 0x07df, 0x09d1, 0x07ee, 0x0509, 0x09b9, 0x023f, 0x02c0, 0x06fa, 0x098d,
0x05d5, 0x0499, 0x0800, 0x016f, 0x0019, 0x0410, 0x010b, 0x01ab, 0x07ea, 0x036f, 0x0094, 0x004e, 0x0a64, 0x06b9, 0x0abe, 0x051a,
0x0295, 0x0078, 0x0112, 0x06a8, 0x08dd, 0x06e9, 0x04d7, 0x08c3, 0x02e4, 0x00f3, 0x0015, 0x09e7, 0x0967, 0x06e2, 0x0650, 0x0508,
0x0882, 0x0028, 0x07f3, 0x00b7, 0x03d7, 0x0504, 0x0143, 0x0016, 0x0995, 0x08b5, 0x0437, 0x0763, 0x04c5, 0x0234, 0x04c7, 0x07da,
0x09bd, 0x027e, 0x051b, 0x01c0, 0x052a, 0x0544, 0x046c, 0x078c, 0x0199, 0x0299, 0x04b6, 0x094a, 0x07d3, 0x053c, 0x0083, 0x017b,
0x00d6, 0x077f, 0x090b, 0x0475, 0x00ab, 0x09cc, 0x0312, 0x0603, 0x0907, 0x07fa, 0x00b9, 0x0909, 0x0889, 0x0360, 0x0247, 0x00cc,
0x054c, 0x0213, 0x054e, 0x0a44, 0x0767, 0x07b0, 0x0074, 0x087b, 0x041e, 0x098a, 0x087d, 0x03ab, 0x069c, 0x06cc, 0x0604, 0x095f,
0x053f, 0x0954, 0x02da, 0x06d1, 0x08f0, 0x09bf, 0x01db, 0x039e, 0x08a8, 0x0ac5, 0x007a, 0x0222, 0x0a8f, 0x042f, 0x0322, 0x01f0,
0x00e3, 0x00f7, 0x0417, 0x09aa, 0x00fc, 0x077a, 0x04e9, 0x0a21, 0x0278, 0x06f7, 0x07ef, 0x08e7, 0x09cd, 0x04aa, 0x0739, 0x09e3,
0x0708, 0x0a72, 0x028e, 0x04a6, 0x04c0, 0x021b, 0x081d, 0x05c5, 0x069a, 0x05bc, 0x06ca, 0x00eb, 0x00ec, 0x0a9b, 0x04f7, 0x07a2,
0x04ec, 0x0338, 0x05b7, 0x0459, 0x043d, 0x02f5, 0x0284, 0x023b, 0x01f5, 0x0979, 0x01c4, 0x027b, 0x0868, 0x043c, 0x0397, 0x048f
};


5. Отримуємо з програматора 1 байт і запам'ятовуємо його, як маркер. Після цього відправляємо в програматор випадкові 4-е байта. Програматор, отримавши ці 4 байта, точно так само, як і ми в п. 4 шифрує їх по тому-ж самому алгоритму RSA і відправляє нас вийшло 8 байт в тому ж порядку (спочатку старший, потім молодший байт з кожного слова). Отримавши ці 8 байт ми повинні перевірити, чи впорався програматор з поставленим завданням і у випадку позитивної відповіді відправляємо йому отриманий раніше маркер.

6. Отримуємо з програматора 1 байт і знову запам'ятовуємо його, як маркер. Потім формуємо в масиві, скажімо, buf11 — 11 випадкових байт і зберігаємо його для подальших дій. Потім хитрим чином відправляємо ці 11 байт в програматор. Хитрість полягає в тому, що ми повинні відправити в програматор 88 байт, які будуть упаковані сформовані нами 11, причому молодший біт маркера використовується для інвертування передаються 11-й байт. Після відправки в програматор 88-й байт, відправляємо в нього отриманий маркер.

Код засмічення на C.
byte _mark; // Отриманий з програматора байт.
byte _buf11[11]; // Масив для 11-і випадкових байт.

for( i=0; i<11; i++ )
{
byte bt = rand();

_buf11[i] = bt;
if( _mark & 1 )
bt = ~bt;

// Пакуємо один байт до 8.
//
for( j=0; j<8; j++ )
{
byte rnd = rand();

byte msk = ( 1 << j );
if( bt & msk )
rnd |= msk;
else
rnd &= ~msk;

// Відправляємо байт rnd з упакованим в нього черговим бітом в програматор.
//
ОтправкаБайта( rnd );
}
}

// Відправляємо в програматор маркер.
//
ОтправкаБайта( _mark );

7. Отримуємо з програматора 1 байт і відправляємо в нього масив з 133 байт, що складається з чотирьох частин.

Перша частина — 48 байт з інформацією про тип адаптера і його «віці» була взята з рідного адаптера «DX0001», в якій текст «DX0001» був замінений на «DX1011».

Ідентифікатор адаптера
{
'D', 'X', '1', '0', '1', '1', 0xff, 0xff, 0xff, 0xff, '1', '6', '0', '6', '2', '4',
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x50, 0x00, 0xff, 0xff, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

Друга частина — 16 випадкових байт.

Третя частина — 22 байта, спеціальним чином сформовані з збережених раніше в buf11 11-й байт.

Код формування 22-х байт на C
byte _buf22[22];

const byte _hash[] =
{
0x58,0x3E,0x09,0x2D,0xFD,0x45,0x68,0x10,0xD5,0x25,0xC7,0xB8,0x28,0x93,0x75,0xDE,
0x57,0x02,0x1E,0x24,0x36,0xB6,0x3A,0x59,0x11,0x6E,0x58,0x91,0xAE,0x53,0x69,0xDF,
0x44,0xA4,0x8B,0xFB,0x76,0x91,0x59,0x3C,0x30,0xB9,0xDA,0x21,0xD8,0x05,0xB4,0x16,
0x4C,0x05,0x78,0x8D,0xB5,0x1C,0x41,0x63,0x4C,0xBE,0xA6,0xCC,0x65,0xB8,0x38,0x1D,
0xE7,0xC6,0xC9,0x19,0xB7,0x73,0xB2,0x7D,0xCD,0x54,0xDC,0xFE,0x67,0x5E,0x79,0x68,
0xB8,0x77,0x73,0x37,0xC8,0x56,0xA2,0x4D,0x9B,0x86,0x56,0x3F,0x26,0x39,0xDE,0xF6,
0xA8,0x13,0xB4,0xBA,0x19,0xDE,0xDF,0x08,0x64,0x2A,0x9F,0xA4,0x3E,0xEE,0x90,0x5B,
0xF0,0xF3,0xC6,0x5F,0x1F,0x84,0x87,0xA3,0x94,0x0D,0x04,0x92,0xDC,0x3C,0xD0,0x6A,
0xD6,0x9B,0xA9,0xED,0x02,0xB0,0xB3,0xBB,0xF3,0x17,0x04,0x93,0x8F,0x18,0x22,0x9B,
0x33,0x0F,0x2A,0x4C,0x72,0x1A,0x0F,0xC2,0x3E,0x4C,0x77,0xAA,0xF2,0x04,0xDC,0x60,
0x68,0x81,0x7B,0x7C,0x60,0xE7,0xD3,0x61,0x3A,0xDA,0x69,0x4A,0x14,0x5A,0xB7,0x31,
0x9F,0xB5,0x60,0x61,0xB4,0x2D,0x80,0x10,0xCF,0x16,0x6B,0xF1,0x08,0x81,0xDA,0x12,
0xA6,0x46,0xF2,0xA2,0x14,0x68,0xAA,0x48,0x94,0x8B,0x9D,0xE3,0xD0,0xFB,0x84,0x74,
0x1C,0x3C,0x94,0x5A,0x3F,0xF0,0x37,0x8C,0xD9,0x7E,0xA7,0x38,0xA4,0xB5,0xA7,0x25,
0x65,0x15,0x7F,0xE5,0x3B,0xD1,0x14,0x1E,0xD3,0xA8,0x47,0x2E,0xD8,0xEB,0xB0,0xAE,
0x4F,0x34,0xF4,0x52,0xC7,0x23,0x9D,0x60,0x98,0x1E,0x2C,0xFC,0xF2,0x96,0xB7,0x83
};

void PrepareBuf22()
{
byte i, j, bt, bt1, bt2, bt3;

for( i=0; i < 4; i++ )
_buf22[i] = rand();

bt2 = (_buf22[1] ^ _buf22[2] ) & 0xEF;
bt3 = _buf22[1] ^ _buf22[3];

_buf22[4] = (byte)((_buf22[0] + _buf22[1] + _buf22[2]) ^ _buf22[3]);
_buf22[1] ^= ( 1 << (_buf22[2] & 7) );

bt = _buf22[2];
bt1 = _buf22[0];
i = 0;
while( i < 10 )
{
bt += _buf11[i++];
bt1 += _buf11[i++];
}
_buf22[5] = bt;
_buf22[6] = bt1;

// ----------------------------------------------------------------

_buf22[7+11] = 0;
_buf22[7+12] = 0;
for( i=0; i < 10; i++ )
{
_buf22[7+11] += _buf11[i];
_buf22[7+12] ^= _buf11[i];
}

_buf22[7+11] ^= _buf11[9];
_buf22[7+12] ^= _buf11[10];
_buf22[7+13] = (_buf22[7+11] + _buf11[10]) ^ _buf22[7+12];
_buf22[7+14] = (_buf22[7+13] + _buf11[9]) ^ _buf22[7+12];

for( i=0; i<15; i++ )
{
bt = (_buf22[7+i] ^ _hash[bt2+i] );
bt = (bt << 2) | (bt >> 6);
bt ^= bt3;
_buf22[7+i] = bt;
}
}

Четверта частина — 47 випадкових байт.

8. Після передачі масиву з 133 байт мікросхема повинна перейти в сон до наступного появи активного високого рівня на ніжці 7, або вона автоматично перейде в стан скидання, у разі, якщо ніжка 7 є сигналом скидання. І далі все повторюється, починаючи з пункту 2.

Виписка одужав хворого
Зрештою адаптер CX1011 був благополучно поставлений на ноги і отримав друге життя в новому програматорі.

Сподіваємося, що матеріал даної статті допоможе читачам благополучно оживити і інші «старі» адаптери, а можливо, виготовити свої власні.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.