- PVSM.RU - https://www.pvsm.ru -
В 2021 году Центризбирком РФ обфусцировал статистические данные выборов на своем сайте. Несколько дней назад я сделал и выложил в комментариях к новости на хабре [1]деобфускатор, чтобы помочь исследователям обнаружить статистические аномалии в результатах. Сегодня взял день отпуска, написать этот пост и поделиться очищенными данными в формате sqlite по по федеральному избирательному округу, которыми поделился @illusionofchaos [2]в посте Получаем данные результатов выборов с сайта Центризбиркома РФ [3]
Под катом я предлагаю еще раз посмотреть, какими техническими методами затрудняли анализ программисты сайта ЦИК-а. Новых идей там нет, решения примитивные , даже обидно что кто-то за них квартиру получил[* [4]]. Вся работа по написанию деобфускатора заняла меньше рабочего дня (точнее вечера + полночи). Основная цель этой статьи не в описании методов, а дополнительный анонс деобфускатора для исследователей. Обсуждать решение применить методики запутывания на государственном сайте куда интереснее, но этим бессмысленно заниматься в интернете.
Итак, они реализовали четыре метода:
На место в DOM, где дожно находиться просто число с результатам добавляют дополнительные элементы, которые отрисовываются где-то за пределами окна браузера.
Единственный интересный момент тут это то, что иногда примешиваются синтаксически неверные правила css у элементов с правильным данными. Самый интересный пример, что я видел, это font-size: 0am
. Видимо расчёт, что люди будут использовать регулярные выражения для считывания этих правил. В деобфускаторе используется честный парсер CSS и поэтому он не восприимчив к таким трюкам.
Страница с результатами с сервера приходит еще более грязная, чем есть в DOM, которые видим в Developer Tools. Дополнительная мелкая подножка есть в JavaScript.
Там определены три функции, которые либо переставляют ячейки местами в таблице, либо убирают один символ, либо просто ставят результат в ячейку.
У меня есть некоторые сомнения в компетентности людей, которые это делали. Им вроде бы известно, что бывают типы данных отличные от строчек, но при этом функция isq_dns
принимает в параметры два целочисленных значения, по которым потом идёт обращение в массив. И совершенно не ясно, зачем ей так старательно передают в аргументы строчки.
В деобфускаторе я это обошёл просто реализовав эти функции на C#.
Для некоторых элементов контент записывается в CSS стиле.
Парсим CSS и меняем значение элемента с такими стилями — скучно.
Самым интересным для меня была игра со шрифтами.
На скриншоте видно, что Ь
отрисовывается как цифра 2.
Если открыть этот шрифт в Windows Font Viewer то будет отображаться полная ерунда. Что же тут произошло?
ЦИК нагенерировал 100 шрифтов (узнал это из данных от @illusionofchaos [2]) в которых по только им известному правилу изменили правила, по которым отображаются коды символов в глифы, которые определены внутри шрифта и определяют то, как графема будет отрисована.
В Open Font это определяется в таблице cmap [5]. Эта таблица используется для того, чтобы можно было переиспользовать глифы для разных букв. Например, латинская A
может иметь такие же правила отрисовки, как и русская А
.
Эту таблицу ЦИК и заменил в каждом из сгенерированных шрифтов по (предположительно) случайным правилам. Это перемешивание не сложно обратить. У каждого глифа есть правила, по которым он отрисовывается. Если один раз применить OCR или вручную разметить символы, и сравнивая эти правила рисования можно однозначно сказать, какая это графема. Но к моей большой радости, нашлось более простое и изящное решение. На сайте был доступен оригинальный шрифт :)
Посколько таблица глифов осталась в том же порядке, что и была до перемешивания, то, имея на руках оригинальный шрифт, можно обратить это перемешивание. В оригинальном шрифте мы можем найти индекс в таблице глифов для любой интересующей нас буквы и использовать этот индекс для понимания того, что изображено на глифе. Строго говоря, это не всегда возможно, но поскольку для перемешивания были выбраны только цифры, то это отображение биективно.
Я проверил и оптимизировал деобфускатор. Он работает примерно полчаса на ноутбуке на данных по федеральному округу, которые предоставил illusionofchaos [6] на GitHub [7] . Эти же данные, прогнанные через деобфускатор, можно тоже скачать на GitHub [8]
Сейчас сделал проект Schwabra [9], для переброса этих данных в sqlite.
Я очень бегло проверил валидность данных, общая сумма по УИК-ам выглядит похожей. Данные в sqlite формате тоже там же [8]
Данные из sqlite
SELECT num, title, SUM(value)
FROM station
JOIN result ON station.id = result.StationId
WHERE name LIKE '%УИК%'
GROUP BY num
ORDER BY num;
SELECT num, title, value
FROM station
JOIN result ON station.id = StationId
WHERE name = 'ЦИК России'
ORDER BY num
1 |
Число избирателей, внесенных в список избирателей на момент окончания голосования |
108171434 |
2 |
Число избирательных бюллетеней, полученных участковой избирательной комиссией |
98614022 |
3 |
Число избирательных бюллетеней, выданных избирателям, проголосовавшим досрочно |
199064 |
4 |
Число избирательных бюллетеней, выданных в помещении для голосования в день голосования |
47386185 |
5 |
Число избирательных бюллетеней, выданных вне помещения для голосования в день голосования |
8081206 |
6 |
Число погашенных избирательных бюллетеней |
42946873 |
7 |
Число избирательных бюллетеней, содержащихся в переносных ящиках для голосования |
8272698 |
8 |
Число избирательных бюллетеней, содержащихся в стационарных ящиках для голосования |
47243246 |
9 |
Число недействительных избирательных бюллетеней |
1167957 |
10 |
Число действительных избирательных бюллетеней |
54347987 |
11 |
Число утраченных избирательных бюллетеней |
1201 |
12 |
Число избирательных бюллетеней, не учтенных при получении |
507 |
13 |
1. Политическая партия "КОММУНИСТИЧЕСКАЯ ПАРТИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ" |
10558234 |
14 |
2. Политическая партия "Российская экологическая партия "ЗЕЛЁНЫЕ" |
500671 |
15 |
3. Политическая партия ЛДПР – Либерально-демократическая партия России |
4185051 |
16 |
4. Политическая партия "НОВЫЕ ЛЮДИ" |
2946703 |
17 |
5. Всероссийская политическая партия "ЕДИНАЯ РОССИЯ" |
27626893 |
18 |
6. Партия СПРАВЕДЛИВАЯ РОССИЯ – ЗА ПРАВДУ |
4139640 |
19 |
7. Политическая партия "Российская объединенная демократическая партия "ЯБЛОКО" |
744065 |
20 |
8. Всероссийская политическая партия "ПАРТИЯ РОСТА" |
286598 |
21 |
9. Политическая партия РОССИЙСКАЯ ПАРТИЯ СВОБОДЫ И СПРАВЕДЛИВОСТИ |
425677 |
22 |
10. Политическая партия КОММУНИСТИЧЕСКАЯ ПАРТИЯ КОММУНИСТЫ РОССИИ |
707968 |
23 |
11. Политическая партия "Гражданская Платформа" |
85716 |
24 |
12. Политическая партия ЗЕЛЕНАЯ АЛЬТЕРНАТИВА |
349820 |
25 |
13. ВСЕРОССИЙСКАЯ ПОЛИТИЧЕСКАЯ ПАРТИЯ "РОДИНА" |
426359 |
26 |
14. ПАРТИЯ ПЕНСИОНЕРОВ |
1364592 |
Сам деобфускатор https://github.com/ulex/izbirkom21 [11]
Автор: Александр Улитин
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/deobfuskatsiya/368086
Ссылки в тексте:
[1] новости на хабре : https://habr.com/ru/news/t/578832/
[2] @illusionofchaos: https://www.pvsm.ru/users/illusionofchaos
[3] Получаем данные результатов выборов с сайта Центризбиркома РФ: https://habr.com/ru/post/579418/
[4] *: https://habr.com/ru/news/t/578832/#comment_23499218
[5] cmap: https://docs.microsoft.com/en-us/typography/opentype/spec/cmap
[6] illusionofchaos: https://github.com/illusionofchaos
[7] GitHub: https://github.com/ulex/izbirkom21/issues/1
[8] GitHub : https://github.com/ulex/izbirkom21/releases
[9] Schwabra: https://github.com/ulex/izbirkom21/tree/master/Schwabra
[10] izbirkom.ru/region/region/karachaev-cherkess?action=show&root=1&tvd=100100225883177&vrn=100100225883172®ion=9&global=&sub_region=9&prver=0&pronetvd=null&vibid=100100225883177&type=242: http://izbirkom.ru/region/region/karachaev-cherkess?action=show&root=1&tvd=100100225883177&vrn=100100225883172®ion=9&global=&sub_region=9&prver=0&pronetvd=null&vibid=100100225883177&type=242
[11] https://github.com/ulex/izbirkom21: https://github.com/ulex/izbirkom21
[12] Источник: https://habr.com/ru/post/579492/?utm_source=habrahabr&utm_medium=rss&utm_campaign=579492
Нажмите здесь для печати.