У меня есть следующие записанные пакеты команд по 32 байта каждый:
3da89fc200180010000000000000000024100001240400010000000000000000
d427eb5a00180010000000000000000024100001240300010000000000000000
984870ff00180010000000000000000024100001240200010000000000000000
4ab8076100180010000000000000000024100001240100010000000000000000
06d79cc400180010000000000000000024100001240000010000000000000000
Предполагается, что первые 4 байта представляют собой контрольную сумму «Ethernet CRC-32» остальных 28 байтов. Я хочу создавать собственные команды, поэтому мне нужно выяснить, как рассчитать CRC.
Я попробовал любой вариант CRC32, который только мог придумать, и даже попробовал «reveng -w 32 -c» на приведенных выше данных, надеясь найти правильные настройки CRC. Не повезло. Я подозреваю, что до и, возможно, даже после расчета CRC происходит какое-то странное переупорядочение данных.
Как я могу подойти к этой проблеме? Существует ли автоматизированный способ попробовать различные варианты перестановки данных?
Несколько советов: для поиска используйте -s
для мести; Reveng ожидает, что CRC будет в конце сообщения, поэтому переместите его для подачи мести; CRC может быть заменен байтами, поэтому попробуйте поменять местами четыре байта.
Можете ли вы дать ссылку на документацию, которую вы цитируете?
Данные, показанные в вопросе, представляют собой команду «CONTINUOUS_IMAGE_DOWNLOAD_CMD» согласно ti.com/de/lit/pdf/swru599 §4.6.2.5.3. Он записан из рабочей эталонной реализации, которая, похоже, не совсем соответствует документации.
Контрольная сумма, судя по всему, генерируется аппаратным модулем CRC: ti.com/de/lit/pdf/swru599 §22.5
Вы можете проверить транскрипцию ваших примеров.
Учитывая столь небольшие различия между сообщениями (изменяются только три бита), после первоначального анализа я могу сказать, что они не противоречат тому, что эти байты являются CRC. Этот вывод основан на единственном зависимом сообщении, в котором есть 3
в меняющейся шестнадцатеричной цифре. Это зависит от сообщений с 0
, 1
и 2
в этой позиции. Если я возьму CRC для этого сообщения и эксклюзивное сообщение или их вместе, я получу CRC для сообщения с 3
. 0x06d79cc4 ^ 0x4ab80761 ^ 0x984870ff == 0xd427eb5a
.
Таким образом, предоставленные данные, какими бы они ни были, согласуются с линейной функцией над GF(2), одной из которых является CRC. Я могу использовать этот подход для вычисления этой функции для трех других возможных значений этих трех битов.
Немного детализируем математику: если я исключаю-или одно из сообщений, включая CRC, со всеми остальными, теперь у меня есть примеры CRC с нулевым начальным значением и нулевым окончательным исключающим-или. Их аннулируют. Поэтому для этого я выбираю сообщение с 0
в другой позиции. Теперь у меня есть сообщения, в которых все нули, кроме цифр 1
, 2
, 3
или 4
. Если я исключаю новые сообщения с 1
и 2
, я получаю сообщение с 3
в этой позиции. Вы обнаружите, что оно соответствует новому сообщению (с CRC) с 3
в этой позиции. Тот факт, что они совпадают, показывает, что набор не противоречит тому, что первые четыре байта являются линейной функцией над GF(2) остальных байтов.
Однако после перебора я обнаружил, что предоставленные данные не соответствуют ни одной 32-битной CRC! Если я предполагаю, что часть, для которой вычисляется CRC, представляет собой некоторое количество смежных байтов предоставленных сообщений, включая, конечно, меняющийся байт, и что предоставленный CRC имеет либо прямой, либо обратный порядок, тогда ни ни обратная CRC с использованием любого 32-битного полинома не будет работать.
Спасибо Марк за отличный вклад.
Я потратил еще некоторое время на изучение остальной части сообщения (за исключением CRC) и обнаружил, что данные упорядочены не так, как я ожидал. Это перестановка байтов. Я видел это с другим кодом TI SPI: они создают пакеты команд в виде массива uint32_t с прямым порядком байтов, но сначала настроили модуль SPI для 16-битной передачи со старшим битом.
Value: 0x00012410 Memory Address 0 1 2 3 Memory Bytes 0x10 0x24 0x01 0x00 Memory Words 0x2410 0x0001 SPI Bytes 0x24 0x10 0x00 0x01
Поэтому я поменял местами записанные пакеты, чтобы воссоздать структуру памяти, которая использовалась для расчета CRC. Чтобы это работало с местью, я также переместил CRC в конец сообщения, как рекомендовал Марк.
Переупорядоченные данные:
18001000000000000000000010240100042401000000000000000000a83dc29f 1800100000000000000000001024010003240100000000000000000027d45aeb 180010000000000000000000102401000224010000000000000000004898ff70 18001000000000000000000010240100012401000000000000000000b84a6107 18001000000000000000000010240100002401000000000000000000d706c49c
Теперь месть подтверждает, что это вполне нормальный CRC:
~/reveng-3.0.6/reveng -w 32 -s 18001000000000000000000010240100042401000000000000000000a83dc29f 1800100000000000000000001024010003240100000000000000000027d45aeb 180010000000000000000000102401000224010000000000000000004898ff70 18001000000000000000000010240100012401000000000000000000b84a6107 18001000000000000000000010240100002401000000000000000000d706c49c width=32 poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926 residue=0xdebb20e3 name = "CRC-32/ISO-HDLC"
Ага! Теперь моя программа грубого перебора тоже его находит.
Вполне возможно, что эти CRC созданы на основе другой системной архитектуры, поэтому, кстати, PHP имеет 3 встроенные версии CRC: crc32, crc32b, crc32c. Возможно, стоит пройти тест, чтобы разобраться в этом. stackoverflow.com/a/62332485/2494754