LINUX.ORG.RU

как подсчитать контрольную сумму сегмента кода?


1

1

Раз уже пятница то сабж. Вопрос не совсем праздный. сталкивался со сбоями оперативы когда проги на ровном месте сегфолтились, а вот после vm.drop_caches=3 всё работало нормально. Хочу запилить чексум и периодически его сверять. От порчи данных не поможет, да. Как и от 100500 других хардварных багов.

Наверно тут свои проблемы внесёт PIC, я в этом не силён. Но хотя бы после запуска проги содержимое кода меняться не должно, верно? При условии что линкер уже всё подгрузил.

Перемещено Dimez из talks

★★★★★
Ответ на: комментарий от vahtu

А дампы нельзя сделать

да я думаю без дампов можно обойтись. Кмк, нехитрой работы с указателями + готовая либа считающая md5 по данным из указателя должно хватить. Но голова уже не варит совершенно. По идее

PIC это position independent code

Какие-то азы есть по http://linuxgazette.net/112/krishnakumar.html,

Похоже mm_struct это то что нужно.

true_admin ★★★★★
() автор топика

Хм, подробнее про проблему можно? А то как-то я не особо сталкивался с таким. На голом железе в принципе не проблема понять где начало _text, а где конец и снять чексумму. А вот под OS как - х.з. запилишь - напиши решение сюда

AiFiLTr0 ★★★★★
()
Ответ на: комментарий от true_admin

да я думаю без дампов можно обойтись

То есть вместо того, чтобы точно выяснить, где косяк, ты хочешь контрольными суммами выяснить, что косяк есть? Или у меня тоже башка не варит :(

vahtu
()
Ответ на: комментарий от AiFiLTr0

Я думаю /proc/self/maps это то что надо. К сожалению, я мало что во всём этом понимаю, но, вроде, тут всё просто. По крайней мере где стэк, где код, а где heap понятно.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

По ссылке ты узнаешь адреса где переменные кладутся в память. Но если у тебя софтина линкуется из овер9к файлов, то порядок линковки будет играть роль, емнип, так что этот способ странен.
На голых мк обычно объявляются символы глобальные _ebss _edata, по которым это можно узнать. Размеры результирующих секций можно складывать уже после компиляции по определенным адресам в принципе, патчем уже после сборки, более красивого средства не знаю.

AiFiLTr0 ★★★★★
()
Ответ на: комментарий от vahtu

чтобы точно выяснить, где косяк

я хочу просто встроить проверку целостности в программу. Не с целью обойти дебаггеры или антихаков понаставить. Просто sanity-check.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Ух ты, да, действительно удобно, все есть.

AiFiLTr0 ★★★★★
()
Ответ на: комментарий от true_admin

В принципе тогда можно делать чексумму text, которую сравнивать с заведомо известным значением в rodata. Чексуммер делается просто: делаем objcopy секции text, прогоняем через crc32sum или что-то иное, сохраняем в хедер, так чтобы оно попало в rodata, и докомпиливаем заново. Ну и в рантайме делаем проверку.

AiFiLTr0 ★★★★★
()
Ответ на: комментарий от AiFiLTr0

порядок линковки будет играть роль, емнип, так что этот способ странен.

да, я думаю не стоит расчитывать что всё останется на месте. Но вот для отдельных символов подсчитать же можно контрольные суммы? Чую, терминология хромает, но смысл понятен.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Для отдельный статически инициализированных НЕ нулем переменных?
Это лезет в data, емнип.
Еще можно в мейне проверить bss на предмет все ли забито нулями. Это делает стартап код, но если память битая - все может быть.

AiFiLTr0 ★★★★★
()
Ответ на: комментарий от true_admin

А это по барабану. Тебе пофиг куда сложится text. Ты знаешь его начало и размер. снимаешь чексумму, сравниваешь с вкомпиленным значением.
сча ради прикола тест наваяю.

AiFiLTr0 ★★★★★
()
Ответ на: комментарий от AiFiLTr0

Тебе пофиг куда сложится text

так он каждый раз разный будет. Сделай несколько раз подряд cat /proc/self/maps и сравни :)

true_admin ★★★★★
() автор топика
Ответ на: комментарий от AiFiLTr0

По-моему, за это отвечает kernel.randomize_va_space

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Причем здесь антихаки?

Дамп программы, откомпилированной с отладочными опциями, содержит все необходимые сведения: точка сегфолта, содержимое регистров, стек, значения переменных... вплоть до строк исходного кода. Указываешь gdb, например, дамп и оригинальный бинарник. Потом (насколько помню) даешь команду bt и смотришь как и при каких условиях прога упала.

А по ссылке, как я понял, разжёвывается элементарная т.н. силовая отладка. Я сам ей пользуюсь, когда контроллеры отлаживаю. Ибо, jtag не панацея. Но у тебя ведь не 8битный ЦП с 8 кб памяти?

vahtu
()
Ответ на: комментарий от AntonK

А ничего, что код может меняться в рантайме загрузчиком?

я так понимаю это в двух случаях: при -z lazy и когда, скажем, делает dlopen. В остальных случаях в багдаде всё спокойно, верно?

Конечно, проверки должны делаться с учётом этого.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от vahtu

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

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

С целевой тачки тебе нужен только дамп! Храни у себя точно тот же бинарь и запускай отладчик на своей машине же.

vahtu
()
Ответ на: комментарий от true_admin

Всегда, когда бинарник грузится по другому адресу, чем было задано при линковке. Как это в линуксах конкретно работает (и работает ли вообще) я не в курсе...

AntonK
()
Ответ на: комментарий от true_admin

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

AiFiLTr0 ★★★★★
()
Ответ на: комментарий от AntonK

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

AiFiLTr0 ★★★★★
()
Ответ на: комментарий от vahtu

С целевой тачки тебе нужен только дамп!

да не нужен никакой дамп :). Читаешь /proc/self/maps, дальше md5sum(start_address, len). И усё.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от aedeph_

ты тоже не понимаешь теорию вероятностей и поверил в то что написано в том пейпре? Хотя, не похоже что ты его даже открывал.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

У меня как-то mplayer глючил. При перемотке падали X. Что я сделал? Компильнул его в отладочном режиме и дождался очередного падения. Натравил gdb на дамп и он мне сказал, что последняя вызванная функция была что-то вроде snd_seek. Я нашел эту функцию. Параллельно погуглил и узнал, что у меня глючная звуковушка (а я уже понял куда копать). В результате я вставил туда дополнительную переинициализация и усе.

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

vahtu
()
Ответ на: комментарий от aedeph_

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

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

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

aedeph_ ★★
()

Нашёл пейпр по «Dynamic Code Checksum Generator» который вроде как учитывает adress space randomization. Правда, там речь о виндах, но всё равно любопытно почитать.

true_admin ★★★★★
() автор топика

какого сегмента - сегмента исполняемого файла (elf), сегмента кода в архитектуре x86 (который в линуксе всегда от 0 до 4Гб)?

Наверно тут свои проблемы внесёт PIC

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

Harald ★★★★★
()
Ответ на: комментарий от Harald

сегмента исполняемого файла (elf), сегмента кода в архитектуре x86 (который в линуксе всегда от 0 до 4Гб)?

т.к. цель выяснить целостность кода во время работы программы то подозреваю, надо проверять сегмент кода.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от bk_

Изначально я планировал делать проверку целостности для своих программ. Но ты подал идею :). Хотя, наверняка антивири такое умеют.

true_admin ★★★★★
() автор топика

В общем, по мотивам ссылки выше:

#! /usr/bin/env python3
import hashlib
import re

r = re.compile(r'(?P<start>[0-9A-Fa-f]+)-(?P<end>[0-9A-Fa-f]+) (?P<perm>\S+) (?P<off>\d+) (?P<dev>\S+) (?P<inode>\S+)\s+(?P<path>\S+)')
with open("/proc/self/maps", 'r') as maps_fd, open("/proc/self/mem", 'rb', 0) as mem_fd:
    for line in maps_fd.readlines():
        m = r.match(line)
        if m and m.group('perm').startswith('r-'):  # if this is a readable ro region
            start = int(m.group('start'), 16)
            end = int(m.group('end'), 16)
            mem_fd.seek(start)  # seek to region start
            chunk = mem_fd.read(end - start)  # read region contents
            print(hashlib.sha256(chunk).hexdigest(), m.group('path'))

(для областей без <path> не считает, надо регексп допилить.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

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

AiFiLTr0 ★★★★★
()
Ответ на: комментарий от true_admin

Я не полностью понял, что ты имеешь ввиду. Поясни, пожалуйста.

Мой ответ был связан с тем, что под iOS широко практикуется aes-шифрование _text сегмента. Это приведет к тому, что чексумма сегмента в исходном бинарнике и кода в памяти будет отличаться. Для этого даже делают дамп _text из памяти запущенного приложения в файл, который потом можно запихнуть в бинарник на место шифрованного кода, предварительно сделав некоторые манипуляции с заголовком исполняемого файла.

Короче говоря, я хотел сказать, что сравнивать чексумму в бинарнике и в памяти - не совсем правильно.

bk_ ★★
()
Ответ на: комментарий от bk_

К сожалению, я слабо знаю структуру ELF-бинаря. То, что я писал выше, актуально для Mach-O. Тем паче, может быть, для линукса шифрование бинарника не актуально ;)

bk_ ★★
()
Ответ на: комментарий от bk_

Я не полностью понял, что ты имеешь ввиду

У меня есть старенький ноут, на нём иногда чудеса происходят. Вот однажды skype выдал что он повреждён. Мне стало интересно как это он понял и можно ли в свою программу встроить такую проверку.

сравнивать чексумму в бинарнике и в памяти - не совсем правильно.

согласен, в общем случае может и не выйдет. Поэтому и спросил что за случаи.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Вот однажды skype выдал что он повреждён.

Это при запуске (ошибка на винчестере) или после некоторого времени выполнения (ошибка работы ОЗУ)?

bk_ ★★
()
Ответ на: комментарий от bk_

или после некоторого времени выполнения (ошибка работы ОЗУ)?

Ошибка либо в оперативе, либо в кэшах проца (встречал такое в dmesg у себя на сервере). Судя по тому что drop_caches помог проблема была (и есть :)) в оперативе.

true_admin ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.