Для обеспечения сохранности содержимого Dynamic RAM (DRAM) его необходимо периодически обновлять. Если значение какого-то бита поменяется самопроизвольно, то можно считать, что память работает не так, как должна. JEDEC (Joint Electron Device Engineering Council — организация, среди прочего, разработавшая спецификацию DDR) определяет, как часто это должно происходить для обеспечения надлежащей работы. Однако некоторых людей больше интересует, как долго данные могут сохраняться после отключения питания DRAM. В этом посте мы расскажем, как это можно измерить, а также поделимся результатами, полученными при исследовании пары протестированных платформ.

Немного теории


RAM (Random-Access Memory, запоминающее устройство с произвольным доступом) — это тип памяти, доступ к которому может выполняться в произвольных локациях почти без различий во времени между разными адресами. В этой статье этот термин будет использоваться для описания памяти единого(*) видимого операционной системе последовательного диапазона адресов.

DRAM (Dynamic RAM) — это тип RAM, хранящий данные в конденсаторах, постепенно теряющих свой заряд и требующих периодического обновления. В этом его отличие от статического RAM (SRAM), не требующего обновления для хранения данных.

Конденсатор и логика, требуемая для доступа к его содержимому, называется ячейкой DRAM. Множество ячеек формирует сетку, адресация в которой выполняется по строкам и столбцам; эта сетка называется банком. Каждый банк (в большинстве стандартных чипов DRAM) параллельно дублируется 4 или 8 раз, то есть каждая пара «строка-столбец» одновременно адресует 4 или 8 битов данных DRAM. Кроме того, каждая DRAM может иметь множество банков, адресуемых по группе банков и адресным битам банка (в DDR4 до 2 битов на каждый).

Простая сетка DRAM с двумя битами строк и двумя битами столбцов

DIMM (Dual In-Line Memory Module) — это модуль, который чаще всего подразумевается под терминами наподобие «модуль RAM» или «планка памяти». Он устанавливается в разъёмы на материнской плате, и его можно легко заменять без каких-либо специальных инструментов. DIMM состоят из чипов DRAM, количество которых кратно 8 (или 9 с ECC), каждый из которых имеют общую адресацию строк, столбцов и банков. Если количество DRAM больше, то они включаются в группы по сигналам выбора чипов; этим управляет DIMM на основании адреса рангов, затребованного платформой. Все линии данных DRAM выстроены параллельно, образуя шину данных DIMM шириной 64 битов (72 бита с ECC).

Отображение непрерывного(*) диапазона адресов системой памяти в многоуровневую адресацию DIMM и DRAM выполняется контроллером памяти платформы. Последовательные системные адреса не обязаны быть последовательными в DRAM. На самом деле, для снижения задержек они часто чередуются (по банкам, группам банков, рангам и даже на уровне DIMM). Обычно производители не публикуют отображение, оно может отличаться в зависимости от версии прошивки, параметров и топологии DIMM. Это означает, что паттерн хранимых данных (потенциально неравномерный) может отличаться для разных платформ, что может мешать целевым атакам, но в среднем скорость затухания заряда хранения данных для разных платформ должна быть более-менее одинаковой.

(*) На практике, особенно на платформах x86, в адресации существует множество «дыр»; они по большей мере используются для совместимости, и их местоположение определяется архитектурой. Память, которая должна быть доступна по этим адресам (часто называемая «украденной памятью», stolen memory), отображается в конец пространства RAM.

Цель этого исследования


Наша главная цель — определить время для потери всех данных из RAM без возможности восстановления после отключения питания платформы.

Для того, чтобы значения данных в DRAM сохранялись, их нужно периодически обновлять. Период операций обновления чётко определён JEDEC. Интервал обновлений называется tREFI. Это значение описывает минимальную частоту обновлений при обычных условиях (температурном диапазоне, тактовой частоте), обеспечивающую надёжную работу памяти. После каждой команды обновления данные из обновляемых ячеек недоступны в течение следующего tRFC (времени цикла обновления). Для повышения производительности в крайне специфичных условиях эту операцию можно отложить или заранее выполнить множество обновлений, чтобы последующие отправлялись позже, однако средний интервал не должен превосходить tREFI. Для реального интервала можно установить значение меньше tREFI, например, когда DRAM работает при повышенных температурах или для повышенной устойчивости к атакам наподобие RowHammer.

Для DDR4 базовое значение tREFI равно 7,8 мкс. Исследованиями было определено, что это максимальное значение, обеспечивающее надёжную работу при стандартных условиях температурного диапазона и частот, то есть при таких условиях не допускаются никакие самопроизвольные смены значений битов, вызванные отсутствием обновления. Однако нападающему необязательно получать каждый отдельный бит, чтобы получить хранящиеся в RAM секреты: успешной атакой может считаться получение любых данных. Кроме того, tREFI определён для крайних значений допустимых диапазонов (наибольшей температуры и частоты), а DRAM обычно работает в более спокойных условиях. После отключения питания тактовые генераторы не работают, поэтому влияние частоты, в основном вызванное электромагнитными помехами между ячейками и линиями, больше не имеет воздействия. Поэтому tREFI не может быть хорошей аппроксимацией для определения скорости затухания зарядов данных, которая способна быть существенно ниже.

Процесс тестирования


Если вкратце, итерация тестирования выглядит так:

  • заполняем RAM по известному паттерну,
  • отключаем питание,
  • снова подаём питание после переменных периодов времени,
  • сравниваем содержимое RAM с ожидаемым паттерном.

Существуют некоторые тонкости, требующие выполнения дополнительных шагов, не связанных напрямую с нашей главной целью. Например, мы можем не использовать всю RAM — прошивка и код, выполняющий запись и сравнение паттерна, тоже расположены в RAM, и эти части памяти необходимо распознавать и пропускать.

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

Предполагается, что изначальное значение ячейки DRAM случайно. Даже спустя бесконечное время каждый бит имеет ту же вероятность смены значения, что и вероятность сохранения записанного значения. Это означает, что максимальный возможный результат — это 50% поменявших значение битов, не считая статистических ошибок. Чтобы избежать любого влияния паттерна на другие биты, мы будем при помощи регистра сдвига с линейной обратной связью (linear-feedback shift register, LFSR) генерировать псевдослучайный паттерн, порождающим значением для которого будет адрес памяти. LFSR обеспечивает результаты с достаточно равномерным распределением, требуя при этом очень мало вычислений.

Для тестирования мы разработали приложение, записывающее сгенерированный паттерн и сравнивающий его при следующем запуске системы. Перед проектированием приложения были приняты следующие допущения:

  1. Работа с физическими адресами с неограниченным доступом к памяти. Операционная система из-за её изоляции памяти усложнила бы работу. Поэтому приложение, работающее с «голым железом», проще спроектировать и разработать, чем работающее в какой-нибудь операционной системе.
  2. Получение схемы распределения доступной памяти. Как говорилось выше, доступна не вся память. Код не может переписывать себя или созданные прошивкой сервисы. Чтобы сделать это, у нас должна быть возможность запрашивать и парсить схему распределения памяти прошивки, которая определяет, какие интервалы памяти необходимо оставить неизменными.
  3. Для записи в память и сравнения используется один и тот же двоичный файл. Это косвенно связано с предыдущим требованием. Если бы мы написали отдельные приложения для записи и сравнения, то они, скорее всего, имели бы разные размеры, что отразилось бы на схеме распределения памяти. Ещё одна причина создания одного общего приложения заключается в очень схожей функциональности, за исключением того, что одна часть кода будет выполнять считывание, а другая запись. Обе должны иметь возможность получения схемы распределения памяти, её парсинга, генерации идентичных паттернов и доступа к памяти.
  4. Память не должна распределяться динамически. Это ещё одно требование для обеспечения постоянства схемы распределения памяти. Динамическое распределение памяти не отражается в изначальной схеме распределения. Все данные должны распределяться статически, а если это невозможно (например, часть необходимых сервисов прошивки распределяет память), то схему распределения памяти нужно получать после выполнения вызовов всех сервисов.
  5. Генерация псевдослучайных паттернов для записи и сравнения.
  6. Приостановка выполнения в заранее заданных точках. Это позволяет выполнять непрерывный мониторинг температуры, если потребуется охлаждение DRAM до ожидаемых значений.
  7. Отображение прогресса записи и сравнения содержимого памяти. Время доступа к RAM относительно равномерно, поэтому достаточно показывать прогресс в процентах. В основном это нужно для того, чтобы понимать, что приложение не зависло (при больших размерах RAM её выполнение может занимать достаточно долгое время), а также для примерной оценки времени, требуемого для каждой итерации.
  8. Сбор статистики о битах, поменявших своё значение. Наряду с общим количеством поменявших значение битов нам нужно собирать статистику по битам, поменявшим значение в каждой линии шины данных DIMM. Из-за архитектуры DIMM каждая такая линия всегда связана с одинаковой DRAM, вне зависимости от адреса.
  9. Вывод результатов в текстовом виде. Приложение должно выводить результаты и состояние оператору на экран и/или через UART. Кроме того, результаты должны сохраняться в хранящийся рядом с приложением файл для последующего анализа.

На основании всего вышеперечисленного мы решили реализовать код в виде приложения UEFI, воспользовавшись gnu-efi. Все представленные выше требования или обрабатываются сервисами UEFI, или легко реализуются на C. Код выложен в репозиторий Dasharo/ram-remanence-tester. В файле README представлена информация о сборке и запуске.

Первые проблемы и изменения в исходном плане


Первые прогоны тестов в QEMU выявили некоторые проблемы. Хотя некоторые диапазоны памяти были помечены как доступные, их содержимое менялось при горячем перезапуске. Причина заключалась в том, что сама прошивка способна распределять память, использовать её и освобождать до запуска приложения. Чтобы обойти эту проблему, мы добавили ещё один этап приложения: после записи паттерна выполняется горячий перезапуск, после чего память сравнивается с ожидаемым паттерном. Если они не совпадают, то вся страница целиком удаляется из тестируемых диапазонов. После этого можно продолжать настоящее тестирование, запланированное изначально.

Ещё одна проблема заключалась в том, что схема распределения памяти иногда менялась. В большинстве случаев она была согласованной, но примерно при каждом десятом прогоне приложение загружалось в другой адрес, скорее всего, потому, что по неизвестным причинам менялось другое распределение. Чтобы обойти эту проблему, мы отфильтровали области меньше 16 МБ и выстроили оставшиеся по основанию 16 МБ и размеру, кратному этому значению. Это не устраняет первопричину проблемы, но существенно снижает вероятность того, что она нам помешает.

После нескольких первых попыток мы также отказались от точного измерения температур DRAM. Они были относительно постоянными и очень близкими к температуре окружающей среды десктопа, а на ноутбуке они постепенно становились выше, даже в режиме простоя. Мы подумали, что это может быть вызвано расположенным поблизости GPU, но пока не тестировали похожего ноутбука без графической карты.

Что касается температуры окружающей среды, то первые итерации прогонов выполнялись в нашем офисе, где температура моментально поднималась до 24 C. Для ноутбука было невозможно получить никаких разумных данных в таких условиях, поэтому мы перенесли тестирование в лабораторию с кондиционированием воздуха, где температуры колебались в пределах 19-20 C.

Тестируемые платформы


Мы решили протестировать две платформы, отличающиеся тем, что одна из них была ноутбуком, а вторая настольным PC, и в одной была установлена память DDR5, а в другой — DDR4. Из-за этого их непосредственное сравнение не имело смысла, да и не было нашей целью.

Первой тестируемой платформой стал ноутбук NovaCustom V540TND с DDR5 SODIMM W-NM56S508G. В настольном PC была установлена память DDR4 MSI PRO Z790-P WIFI с DIMM Kingston KF432C16BB/4. Как видите, мы выбрали для тестирования малый размер памяти. Хотя при большем количестве модулей памяти результаты могут немного отличаться из-за худшего воздухотока, мы хотели сэкономить время, потому что вообще не были уверены в получении полезных результатов.

Если статья будет интересна читателям, в будущем мы можем расширить тестирование и рассмотреть другие конфигурации оборудования.

Результаты


Ниже показаны результаты, разделённые по платформам, что совпало с разделением на поколения DDR. При всех тестах влажность воздуха была постоянной (33%). Температура несущественно менялась, она указана рядом с результатами.

В результатах показано количество изменившихся битов, разделённое между переходами из 1 в 0 и из 0 в 1, а также среднее двух переходов. На горизонтальной оси отложен номер бита на шине памяти.

▍ Ноутбук — DDR5 SODIMM


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

Наши лучшие три замера были равны 36,06%, 39,28% и 41,04%, а остальные оказались столь близкими к наихудшему возможному результату (50%), что их вполне можно отбросить как статистическую ошибку. Все данные оказывались утерянными спустя одну секунду после отключения питания.

20,1 C, время без питания примерно 0 с, 36,06% изменившихся битов

19.3 C, время без питания примерно 0 с, 39.28% изменившихся битов

19.4 C, время без питания примерно 0 с, 41.04% изменившихся битов

▍ Настольный PC — DDR4 DIMM


Эта платформа продемонстрировала гораздо более высокие показатели сохранения данных. Мы выполняли замеры с интервалами по 10 секунд, начиная с мгновенного включения питания и до 2 минут.

19.8 C, время без питания примерно 0 с, 0.08% изменившихся битов

19.5 С, время без питания 10 с, 6.32% изменившихся битов

19.4 C, время без питания 20 с, 13.63% изменившихся битов

19.4 С, время без питания 30 с, 23.39% изменившихся битов

19.3 С, время без питания 40 с, 35.01% изменившихся битов

19.4 С, время без питания 50 с, 42.81% изменившихся битов

19.3 С, время без питания 60, 46.22% изменившихся битов

19.3 С, время без питания 70 с, 47.71% изменившихся битов

19.2 С, время без питания 80 с, 48.57% изменившихся битов

19.2 С, время без питания 90 с, 48.96% изменившихся битов

19.2 С, время без питания 100 с, 49.26% изменившихся битов

19.1 С, время без питания 110 с, 49.43% изменившихся битов

19.2 С, время без питания 120 с, 49.51% изменившихся битов

Получив эти замеры, можно построить график сохранившихся битов в зависимости от времени без питания:


Заключение


Обе платформы демонстрируют, что со временем данные теряются, но скорость на протестированных платформах существенно различается. Тех показателей, для которых хватало меньше секунды на ноутбуке с DDR5, нельзя было получить даже спустя две минуты на десктопе с DDR4.

На обеих платформах заметно влияние топологии DIMM. В случае DDR5 SODIMM распределение изменений в битах 0-31 приблизительно согласуется с распределением изменений в битах 32-63, особенно для средних значений. В младшей половине больше переходов из 0 в 1, что в старшей половине зеркально отражается в переходах из 1 в 0. Видна и граница между DRAM, хоть она и не так заметна, как в ситуации с DDR4 DIMM. Результаты последней демонстрируют чёткое различие между группами из 8 последовательных битов, а среднее в группе остаётся практически постоянным.

В течение одного прогона некоторые DRAM начинают терять свои данные быстрее остальных. Нельзя сказать, что это коррелирует с их максимальным временем сохранения — взгляните на группу битов 40-47 в DDR4. При задержках включения питания в диапазоне 10-50 секунд эта группа всегда теряет наибольшую часть своего содержимого, но после ситуация не ухудшается так же быстро, как в других группах.

Для DDR4 график процента утерянных данных в функции от времени демонстрирует, что количество утерянных данных быстро растёт при малых задержках, но потом замедляется, когда приближается к 50%. Кроме того, график сглажен слева, это может говорить о том, что к измерениям времени добавляется какая-то постоянная систематическая погрешность. На самом деле, после подачи питания на этой платформе светодиод питания загорается спустя примерно 5 секунд.

Подведём итог


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

Telegram-канал со скидками, розыгрышами призов и новостями IT ?

Комментарии (21)


  1. Soorin
    18.12.2024 13:10

    В конце восьмидесятых, при отладке собранных ZX Spectrum (К565РУ5, период регенерации от 2мс),порой при очередном включении перед сбросом на экране была видна картинка, частично сохранившаяся со времени отключения питания (проходили минуты).


    1. YMA
      18.12.2024 13:10

      Тогда были старые блоки питания с толстенными конденсаторами на выходе. В школе стояли IBM PS/2 - можно было щелкнуть тумблером питания туда-сюда, и компьютер продолжал работать ;)

      А про атаку на считывание содержимого памяти пишут давно, вот например https://xakep.ru/2008/02/28/42561/ - предлагают перед снятием охладить жидким азотом.


    1. TEXHOPYK
      18.12.2024 13:10

      Мне досталась аномальная Yamaha из состава КУВТ-2. Всем остальным компам в классе было достаточно моргнуть выключателем питания для сброса содержимого памяти, но моей могло не хватить и минуты и игра загружалась вновь, ошибок при выполнении не было.


      1. rbdr
        18.12.2024 13:10

        О, наши люди! :) У меня тоже есть КУВТ2 (ученический) и раньше еще прикупил Panasonic MSX2+.

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


        1. Pyhesty
          18.12.2024 13:10

          не совсем памяти, а регистра маппера, который указывал на страницу памяти, по какой-то причине он не имел сброса, но рано или поздно без питания переключался на нулевой банк, где находилось ПЗУ. Если бы этот маппер имел сброс, то эффекта который мы наблюдали в детстве не могло бы возникнуть, всегда при нажатии на сброс был бы бейсик) а так да, пиратские игры Konami, часто не перезапускались по сбросу)))


  1. robert_ayrapetyan
    18.12.2024 13:10

    Не соответствуют ли полученные графики характеристикам конденсаторов, установленных в цепочках питания памяти?


  1. Sly_tom_cat
    18.12.2024 13:10

    Предполагается, что изначальное значение ячейки DRAM случайно. 

    А вот тут можно быть точнее. Если холодную (во всех смыслах) память подключить к питанию регенерации, то там довольно часто повторяется примерно одна картина распределения 0 и 1.

    На стареньких компах соответствующий "матрас" можно было увидеть на экране до инициализации экранного адресного пространства.

    Т.е. во что сбросится бит можно более точно предсказать если эту картинку снять с памяти после ее холодного включения.


    1. Deosis
      18.12.2024 13:10

      В исследовании вообще никак не объясняется самопроизвольное переключение битов из 0 в 1.

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

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

      А то что по стандарту период регенерации заряда считается в микросекундах, и при отсутствии питания больше нескольких миллисекунд, сохранность содержимого памяти никак не гарантируется, что видно на ноутбучных планках, исследователи просто забили.


      1. sappience
        18.12.2024 13:10

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

        Или некоторые ячейки используют инверсную логику (заряжен - 0, разряжен - 1).


      1. Sly_tom_cat
        18.12.2024 13:10

        Там все сильно сложнее.

        Старт работы любого устройства - это довольно не простой переходный процесс.
        Если в цепи есть индуктивности и конденсаторы (а там есть и то и другое) то это довольно "веселый" процесс. Если заносила нелегкая на уроки по электротехнике на эту тему в вузе то поймете о чем я.
        Так вот теперь еще представьте эти процессы на матрице с кучей элементов. Что там куда потечет во время переходных процессов на старте - будет не очень просто рассчитать, но в некоторых конденсаторы заряды вполне могут попасть. Но по моим наблюдениям все-таки там есть сходимость ибо на своем первом компе (спаянный проводами МГТФ Специалист, там какие-то 565РУ<не помню цифру, но 16 мегабит на схему>) я видел после запуска всегда одинаковый "матрас" на экране.


  1. VADemon
    18.12.2024 13:10

    Не глубоко, но хорошо, потому что последние исследования на этот счет были как бы не времен DDR2.

    Непонятные показатели DDR5 могут быть связаны с применением ECC.


    1. WVitek
      18.12.2024 13:10

      Непонятные показатели DDR5 могут быть связаны с применением шифрования, внедрённого в свежие процессоры как раз в целях предотвращения "краж" содержимого памяти...


      1. VADemon
        18.12.2024 13:10

        Оно хоть где-то в consumer линейках доступно?


  1. vp7
    18.12.2024 13:10

    Очень не хватает оценки при пониженной температуре оперативки, хотя бы 2 среза: небольшой минус (-5 .. -2), большой минус (охлаждение потоком жидкого азота до цифр уровня -50 и ниже) и сравнить результат с комнатной температурой.

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



  1. belav
    18.12.2024 13:10

    Когда-то делал видеоадаптер для компьютера, как раз выводил кусок памяти на экран монитора. Если вывести картинку (записать в определенную область памяти) и удерживать сброс на системнике, то картинка "таяла на глазах". Через секунд 20...25 разобрать, что было становилось не возможно.


  1. VenbergV
    18.12.2024 13:10

    Около 30 лет назад, "упражнялся" кодом, на TASM с параметром регенерации памяти на IBM XT клоне, под MSDOS. Помню что удавалось получить прирост быстродействия до 12%. Стабильно работало до 10%.


  1. 15432
    18.12.2024 13:10

    Как вы обошли смену сида маскирования DRAM в контроллере памяти при отключении питания? Или вы не отрубали полностью питание на чипсет?


    1. sappience
      18.12.2024 13:10

      Это же перевод.


  1. electrodummy
    18.12.2024 13:10

    Как долго можно извлечь данные из мозга после смерти человека?


  1. PriFak
    18.12.2024 13:10

    DIMM состоят из чипов DRAM, количество которых кратно 8 (или 9 с ECC)

    Неправда
    на серверных планках часто по 17 чипов - 16+1 для корекции. Также число чипов не всегда кратно 8 - оно сокрее кратно двум, так как есть модули на 4 чипа, а чип корекции всегда один, поэтому единственная планка с числом кратным 9 - это планка на 9 чипов, потом идет на 17 (которое вообще простое число и ничему не кратно).
    Если коротко - на обычной четное количество чипов, на ECC REG нечетное.