Pull to refresh

Нелепые глупости

Reading time2 min
Views1.3K
Так уж случилось, что в свободное от основной работы время я начал писать программы. Правильные (возможно) программы, программы, которые мне нравилось (и нравится) писать – программы, которые мне нравится использовать. Пока их ажно целых две ). В принципе, это достаточно большие программы (более 2 Мб исходников каждая). При создании их доводилось натыкаться на “непонятные странности” достаточно “неправильное“, на первый взгляд поведение компилятора/программы и операционной системы. После разбора полетов, в очередной раз удостоверялся, что я СЗЗБ (сам себе злобный буратинко). В любом случае – пара примеров, как я глючил и как делать не надо (все под вин32 – интел86).



Пример первый

Оса(название то какое ) ). Программа, перехватывающая вызовы функций сторонних процессов к дллкам, и позволяющая изменять входные/выходные параметры этих перехваченных функций. Сами функции-обманки исполняются на стековой машине – с ними проблем нет. Но, чтобы им передать управление, нужно инициализировать стековую машину. Для этого нужно чуть-чуть памяти, куда прыгнет джамп либо из начала перехватываемой функции (конечно при условии ее успешного дизассемблирования), либо из таблиц импорта других PE-файлов (екзешки и дллок), загруженных в память процесса. Память можно взять в трех местах:

• Найти место в секциях загруженного файла – в общем случае невозможно.
• В стеке – возможно, но хлопотно.
• Куча – это и выбрал.

Оса загружала дллку в память стороннего процесса, та выделяла память для байт-кода и заполняла ее, выделяла память для чистого x86 кода, подготавливающего стековую машину и вызывающего ее. И все работало. Везде. Почти везде). Именно на висте два экземпляра запущенного Far manager с интервалом менее 3 секунд, с перехваченными функциями обращения к файлам умирали. Процессы говорили, что они выполнили недопустимую операцию и будут закрыты. Просидев с час за отладчиком, осознал простейшую истину – память, выделенная процессу из кучи, может быть не исполняемая. Почему-то раньше это и в голову не приходило (хе странно почему). Иногда, при определенных ситуациях определенные версии виндов при выделении памяти оператором new могут сделать то, на что имеют право – дать память с неисполняемым атрибутом (только чтение и запись). Дальше уже используя WinApi функции надо присвоить этой (если не ошибаюсь, странице или страницам) памяти атрибут исполнения, если хочется непосредственно в этой памяти выполнять машинный код.

Пример второй

Visual C++ vs OSProtector

Протекторы, они пытаются защитить программы от злых хакеров). И им тоже нужна память, память в исполняемом файле. Память они берут либо, увеличив размер последней секции, либо добавив новые, либо вообще заменив старые (как правило, с упаковкой секций). В любом случае протекторы меняют таблицу секций (расположенную в начале файла). На текущий момент Visual C++ в стартовом коде скомпилированных приложений проверяет целостность таблицы секций. Если она изменилась, то Runtime error R6002 floating point not loaded при старте приложения. При попытке защитить тот же Far manager (v 1.7) протектором все было хорошо. При попытке защитить Far manager (v 2.0) протектором все хорошо не было – очевидно он скомпилен компилятором более новой версии. Гугленье показало: www.manhunter.ru/underground/65_runtime_error_r6002_floating_point_not_loaded.html

Так или иначе, OSProtector, перед передачей управления стартовому коду, теперь восстанавливает исходные атрибуты секций защищенного файла.
Tags:
Hubs:
Total votes 64: ↑38 and ↓26+12
Comments34

Articles