Доброго времени суток всем. Возникла задача: для каждого из процессов, находящихся на данный момент в памяти, построить уникальную контрольную сумму и сравнить с контрольной суммой, расчитанной по соответствующему PE-файлу из которого процесс был порожден. Эти манипуляции необходимы для того, чтобы быть уверенным в том, что именно этот экзешник является "автором" процесса. Из PEB каждого процесса достаю полный путь к EXE, ImageBase, но что делать дальше? Ведь по адресу ImageBase лежит образ с выпрямленными релоками и подгруженными DLL, над ним мог поработать распаковщик (если файл был запакован) и пр. и пр. Естественно, что контрольная сумма этой области памяти и EXE-файла будут разными... Может быть считать сумму только заголовка? Или какой либо секции? Буду признателен за любой совет.
Сути фразы не уловил, ну да ладно... Ничего считать не надо - в PE заголовке в OptionalHeader есть такое поле, называется CheckSum. Так вот по сути это и есть контрольная сумма файла. Надо только сравнить его значение в файле на диске и в уже запущенном файле. Различные упаковщики вряд ли будут его стирать, ибо его значение в целом не влияет на работу приложения - они скорее потрут что-нить вроде NumberOfSections.
суть проста - берем PE-файл (EXE), называем его x.exe и запускаем из директории C:\DIR. В результате создается процесс и в PEB этого процесса полный путь - C:\DIR\x.exe. Теперь переименовываем x.exe в temp.exe, берем другой EXE файл - y.exe, переименовываем в x.exe и запускаем из той же директории C:\DIR. В результате в памяти находятся два процесса и у обоих в PEB указано, что они стартовали из C:\DIR\x.exe, но на самом деле, если теперь расчитать контрольную сумму C:\DIR\x.exe и обоих процессов в памяти (вот только как?) или определенной фиксированой части, которая не меняется загрузчиком PE Windows, то мы узнаем кто из них на самом деле стартовал из текущего C:\DIR\x.exe. По поводу Checksum в хеадере... это одно из многочисленных полей, которые есть в стандарте MS на EXE (PE) и которые заполняется чем Бог на душу положит еще со времен DOS. Большинство линкеров ничем его не заполняют, кто угодно может записать туда что угодно - загрузчик ОС игнорирует находящуюся там информацию. Самостоятельно заносить туда расчитанную контрольную сумму нежелательно по ряду причин... также нежелательно создавать CRC в дополнительных файловых потоках, как например это делает KAV 5.x и т.п.
Тот кто будет заниматся переименованием, сможет и подправить всё что угодно в памяти процесса, хеш можно правильно (для всего файла) посчитать только в момент размапливания (перед инициализацией) а для уже запущеных практически нереально, наверное лучше копать в сторону ядра (открытых хендлов и id процесса), оно то уж точно знает какой физ.файл принадлежит процессу чтобы подкачивать
Тогда считать CRC по DOS header'у. Его тоже вряд ли кто будет тереть. А лучше всего скомбинировать несколько методов: скажем, OptionalHeader.Checksum, CRC по DOS header'у и, к примеру, CRC по таблице секций. Если 2 из трёх различны, с вероятностью в 99% файл не является автором процесса.
<Ничего считать не надо - в PE заголовке в OptionalHeader есть такое поле, называется CheckSum. Так вот по сути это и есть контрольная сумма файла. Надо только сравнить его значение в файле на диске и в уже запущенном файле.> чаще всего там стоит 0, если это не .sys. <Тогда считать CRC по DOS header'у. Его тоже вряд ли кто будет тереть. А лучше всего скомбинировать несколько методов: скажем, OptionalHeader.Checksum, CRC по DOS header'у и, к примеру, CRC по таблице секций. Если 2 из трёх различны, с вероятностью в 99% файл не является автором процесса.> можно и CRC посчитать, но только у кодовыъх секций, глупо у секций данных. Кроме того, смотрите, файл может быть упакован, что не редкость, да даже и в нормальном неупакованном бинарнике загрузчик свое дело сделает, позабавится с релоками. Контрольная сумма в любом случае исказиться. Есть варианты, к примеру перехватить CreateProcess, NtCreateProcess. Перехватить функции MMF. В режиме ядра зарегистрировать callback PsSetCreateProcessNotifyRoutine(), либо есть еще одна функция доточно не помню, вызыветсчя при загрузке образа в память. Варианты есть. Но вряд ли те, что вы перечислили.
Если файл сжат упаковщиком, то секции пакер уж точно изменит - не вижу смысла считать CRC по секциям. О чём и речь, поэтому считать CRC по заголовку, а не по секции. PE-header тоже может быть частично потёрт тем же пакером\протектором. Это-то понятно, но применимо ли это в случае sherion - висит ли его программа в памяти постоянно или только время от времени сканирует? с каким уровнем привелегий итд. Судя по фразе его программа на момент запуска сканирует память, т.е. перехват MMF не катит.
Чтобы было немного понятнее опишу саму поставленную задачу, которая довольно проста в плане описания Итак, нами создана программа, которая должна выполняться в "доверенной" среде, то есть программы загруженные в память до старта нашей программы и запускаемые во время ее выполнения должны находиться в "белом" списке. Не важно каков критерий при отборе программ для такого списка. Для однозначной идентификации программы, которой можно доверять стоится хэш содержимого ее EXE файла и заносится в защищенное хранилище. Теперь при старте нового процесса, в случае если наша программа работает, мы расчитываем хеш стартующего экзешника, ищем по базе, если находим - старт разрешен, в противном случае - отказ. Написан драйвер (огромное спасибо Four-F и Ms-Rem за их статьи на wasm.ru), перехватывающий ZwCreateProcess и ZwCreateProcessEx и проверяющий стартующий процесс, кроме того, драйвер по запросу строит список процессов в памяти,получая их Pid и пути до исходных EXE из PEB или EPROCCESS по известному алгоритму. Перехват также включается по запросу из нашей программы при старте. Это работает. Но вот с уже находящимися в памяти процессами - проблема, т.к. не совсем понятно как считать хеш сумму по памяти процесса чтобы она потом совпала с хешем экзешника. Конечно можно постоянно мониторить драйвером моменты старта процессов и хранить хэши их экзешников в памяти вне зависимости от того, запущена наша программа или нет, но расчет MD5 для EXE файла весом, скажем в 50 мегабайт и находящего в момент старта на сервере, канал до которого 10 МБит занимает ощутимое время и без надобности думаю делать этого не стоит, хотя тут есть варианты. Судя по всему, после того как загрузчик загрузит PE в память связь с файлом на диске разрывается, лищь в PEB и в FileObject полученном из EPROCESS остаются строки указывающие на исходный файл. Понятно, что метод недостаточно надежен, понятно что возможен DLL инжектинг в память процессов и самой программы чтобы обойти защиту - это дело второе. Но пока хотелось бы понять реализуем ли сам механизм контроля по контрольным суммам, ведь, к примеру, файрволл Outpost мониторит CRC DLL-ок и экзешников, имеющих доступ к сети, на предмет их изменения. Может немного путанно объяснено, но как смог
Понятно, похожее обсуждалось http://www.wasm.ru/forum/index.php?action=vthread&forum=6&topic=12152 , но для уже работающих процессов связь с файлом на диске не разрывается, где-то она есть, ведь ядро подкачивает неизмененные страницы в нужный процесс именно из образа файла (его создавшего), попробуй exe'шник из сети запустить, добится нехватки памяти и вытянуть кабель - получишь ошибку и смерть процесса
Ну и где сказано, что они считают хеш по памяти? Там SHA-1 образа сверяется с базой перед его запуском
вот и недостаток для постоянно мониторящего процесса этого достаточно, для моего случая, к сожалению нет ладно, буду копать в сторону слабодокументированных MS структур ядра, которые к сожалению, меняются от версии к версии. млин, неблагодарная как выяснилось, задачка
Я об этом и говорю, тебе надо попросить ядро размапить к себе тот-же образ модуля, которое оно мапит в указанный процесс и посчитать его хеш, ни о каких путях и переименованиях думать не надо, может какой-то DuplicateHandle, я не спец по низкоуровню, пусть поправят
хм... поиски ни к чему не привели перекопал весь EPROCESS, всего много, глаза разбегаются, но зацепится особо не за что... народ, если кто-то знает как получить копию хэндла EXE файла, породившего процесс в памяти (если этот хэндл существует) или адрес/хендл секции этого же файла ткните носом, буду очень благода...
Точно помню были вопросы типа "как узнать кто держит файл", "как удалить\писать в самого себя (т.е. exe)", думаю они из тойже оперы, вот только те топики найти ...
Хеш в памяти вычислить практически невозможно по следующим причинам: 1) Процесс может иметь глобальные переменные находящиеся в секции данных (они могут изменяться) 2) Секции данных и кода могут быть соединены. 3) Процесс может изменять и свою секцию кода (упаковщики, протекторы и.т.п.) Подсчет контрольной суммы секции кода конечно можно сделать, но этот способ слишком часто будет давать неправильные результаты, так что врядли пригоден для практического применения. Лучше будет запретить запись в память со стороны других процессов (при этом нужно учесть, что csrss.exe должен иметь доступ к памяти любого процесса, иначе нарушается нормальное функционирование системы). В windows2000 существует, в XP нет. Адрес секции будет равен ImageBase экзешника, хэндл секции в winxp также не существует.
Ms Rem А, я не так понял фразу "хэндла EXE файла, породившего процесс в памяти", думал, имеется ввиду хэндл родительского процесса.