• Работаем с Compound File

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

      Вообще для чего обычно используют составные файлы?
      Для всего, что нужно хранить в некоем контейнере (NoSQL подмножество).
      К примеру, файлы старых версий Microsoft Office от 97 до 2003 включительно (состоящие на самом деле из нескольких десятков файлов), хранились как раз в составном файле. Сейчас тоже хранятся, только в качестве контейнера используется ZIP.

      Инсталляционные пакеты MSI тоже являются составными файлами, и даже файл кэша эскизов папок Thumbs.db использует этот формат.

      Правда для того же Word есть целый комплекс утилит (Recovery for Word, Word Recovery Toolbox, Munsoft Easy Word Recovery) восстанавливающих, ну или по крайней мере пытающихся восстановить, поврежденные документы. Выводы можете сделать сами.
      Хотя, при должной работе с составными файлами проблему их повреждения можно решить (и я покажу как).

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

      Кстати, нюанс. Перед началом статьи я провел опрос на нескольких форумах, и выяснилось, что подавляющее большинство разработчиков не работают с составными файлами, причем по простой причине — не слышали что это такое.
      Вот сейчас и закроем этот пробел.
      Читать дальше →
      • +12
      • 8,3k
      • 6
    • Пара слов о кэшировании данных при чтении и смартпойнтерах

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

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

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

        В данной статье я поделюсь тремя наработками, которые вышли как раз из таких вот «папок с ништяками» и уже не первый год применяются в наших боевых проектах.
        Будет немножко ассемблера — но не пугайтесь, он там только в виде информационной составляющей.
        Читать дальше →
      • Поддержка MultiTouch + Gestures в Delphi XE4



          Как-то незаметно для меня прошли все эти новые веяния в виде активных мониторов, на которые пользователь может тыкать пальцами. И знать бы о них не знал, кабы месяца три назад начальство не приобрело себе ноутбук, который можно порвать на две части (экран отдельно, клавиатура отдельно), причем не Surface какой-то, пропиаренный MS, а уже самый проходной у пользователей – от ASUS, за гораздо меньшие деньги (относительно).
          Да и закуплен был данный девайс не просто так – задача выросла оттуда, откуда и не ждали.

          Де юре: мы проводим огромное количество семинаров в месяц, и вот именно на них, нашим лекторам начали демонстрировать несовместимость нашего ПО с этим пресловутым тачем.

          Де факто: на почту саппорта начали сыпаться гневные письма пользователей плана – «я два раза тапнула, а оно не тапнулось, может не так тапнула?»
          А начальство все это скрупулезно отслеживало на своем «порватом» ноутбуке и готовило ТЗ.

          И вот настал тот день. Мне на рабочий стол был воздвигнут третий монитор, 23 дюйма от LG (с поддержкой Touch ввода аж 10 пальцами) и поставлена задача – это должно заработать в течении трех дней!

          А работаю то я в XE4 – беда.
          Читать дальше →
        • Анализ приложения защищенного виртуальной машиной

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

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

            Для более или менее адекватного восприятия статьи потребуется минимальные знания ассемблера (его будет много) а так-же навыков работы с отладчиком.

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

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

            В качестве реципиента, по совету одного достаточно компетентного товарища, я выбрал немножко старый (но не потерявший актуальности, в силу качества исполнения) keygenme от небезызвестного Ms-Rem.

            Вот первоначальная ссылка, где он появился: http://exelab.ru/f/index.php?action=vthread&forum=1&topic=4732
            А потом он попал вот сюда: http://www.crackmes.de/users/ms_rem/keygenme_by_ms_rem/
            Где данному keygenme был выставлена сложность 8 из 10 (*VERY VERY* hard).
            Хотя, если честно, это слегка завышенная оценка — я бы поставил в районе 5-6 баллов.

            Пожалуй, начнем.
            Читать дальше →
          • Здравствуйте, я ошибка 217 и я вам ничего не скажу

              Вероятно многие встречались с таким вот «партизаном» при старте или завершении приложения:



              Очень информативное сообщение, сразу понятна причина ошибки, место и способ ее решения.
              Впрочем, если без шуток, что это вообще такое?
              Конечно-же это исключение, но ни тип исключения, ни его описание нам не доступны — просто «Runtime error 217» и адрес, а дальше сами…

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

              И тратил бы его в дальнейшем, если бы на днях со мной не связался Виктор Федоренков и не рассказал о своих мыслях по поводу ошибки за номером 217.
              Читать дальше →
            • Карта памяти процесса

                Задумывались ли вы над тем, как именно используется память, доступная вашей программе, да и вообще, что именно размещается в этих двух-трех гигабайтах виртуальной памяти, с которыми работает ваше ПО?

                Спросите, зачем?
                Ну как же, для 32-битного приложения 2-3 гигабайта – это ваш лимит за пределы которого без использования AWE вы выбраться не сможете, а контролировать собственные ресурсы все же желательно. Но даже и без этого просто с целью разобраться…

                В прошлых статьях я описывал работу отладчика, где производились модификации памяти приложения, находящегося под отладкой. Эта статья является продолжением данного материала. И хотя к отладчику она не будет иметь отношения, но вот к процессу отладки – самое непосредственное…

                Давайте посмотрим, как именно программист работает с памятью при отладке (особенно при отладке стороннего приложения, проще говоря, при реверсе):

                1. Как правило, самой частой операцией будет поиск значения в памяти приложения и, к сожалению, данный функционал почему-то не предоставлен в отладчике Delphi (собственно, как и в MS VC++).
                2. Модификация системных структур (PEB/TEB/SEHChain/Unwind/директорий PE-файлов etc...) будет происходить гораздо проще, когда поля структур размаплены на занимаемые ими адреса и представлены в читабельном виде.
                3. Отслеживание изменений в памяти процесса (практически никем не предоставляемый функционал, реализованный в виде плагинов к популярным отладчикам). Действительно, зачем трассировать до посинения, когда достаточно сравнить два снимка карты памяти, чтобы понять, тут ли происходит нужная нам модификация данных или нет?

                Да, собственно, вариантов использования много.

                Впрочем, если без лирики, утилит отображающих более-менее вменяемую информацию о карте памяти процесса, которую можно применить для отладки, очень мало.
                Читать дальше →
              • Сортировка списка по аналогу «Проводника Windows»

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

                  В данной мини-статье я рассмотрю одну из таких «хотелок».

                  Допустим у вас есть список элементов, отображаемый в TListView, вы пробуете его отсортировать и получаете вот такой результат.

                  image

                  Не красиво, почему это второй элемент с именем «101» находится не на своем месте? Ведь это число, а стало быть место ему как минимум после элемента с именем «2». Да и «New Folder (101)» явно должна быть после «New Folder (2)». Ведь в проводнике все выглядит нормально.

                  image

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

                    Буквально на днях ко мне обратились с вопросом.

                    А зачем нужен префикс LOCK, или его аналог InterlockedDecrement при вызове процедуры _LStrClr из модуля System. Данная процедура декрементирует счетчик ссылок строки и при его обнулении освобождает память, ранее занятую строкой.

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

                    В принципе предпосылка интересная, но…
                    Читать дальше →
                  • Нужны ли недокументированные API?

                      В чем прелесть высокоуровневых языков программирования?
                      Программист перестает задумываться о том «как оно на самом деле фунциклирует» и выдает на гора тонну не сопровождаемого кода, который иногда даже работает, но периодически подтормаживает. Более того, частенько, он даже не собирается об этом задумываться, так как у него банально отсутствуют необходимые знания (увы, так сейчас учат).

                      Потом из всего этого появляются такие умные слова как «паттерны проектирования», внутренние фреймфорки, на которые без слез не взглянешь и прочая светотень включая техдокументацию, которую нужно написать так, чтобы ее смог понять некий сторонний пейзанин, который к программированию, по сути (да и по должности), имеет самое отдаленное отношение.
                      Слова умные, для высокоуровневого кода вполне даже может подходят, но…

                      А потом, выполнив очередной умный «паттерн» он начинает разбираться — где же тормозит алгоритм. Причем, если программист более настырен, он изучает реализацию VCL и иногда даже докапывается до сути, где получается так, что тормоза упираются в вызовы известных ему по документации API, пройдя к которым он со спокойной душой останавливается и закрывает тикет в багтрекере фразой: «функция ХХХ тормозит, вариантов обхода нет».

                      Не встречались с ситуацией?
                      Значит повезло…

                      Читать дальше →
                      • +10
                      • 8,4k
                      • 4
                    • Правильное применение сплайсинга при перехвате функций подготовленных к HotPatch

                        В прошлой статье я рассмотрел пять вариантов перехвата функций включая их вариации.

                        Правда в ней я оставил не рассмотренными две неприятных ситуации:
                        1. Вызов перехваченной функции в тот момент, когда ловушка снята.
                        2. Одновременный вызов перехваченной функции из двух разных нитей.

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

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

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

                        Перехват сплайсингом через JMP NEAR OFFSET или PUSH ADDR + RET (наиболее уязвимый к данным ошибкам) рассмотрен не будет, т.к. по хорошему, без реализации дизассемблера длин, заставить данный вариант перехвата работать как нужно не получится.

                        Читать дальше →