3 April 2010

Коварный и ужасный sndrec32.exe

AssemblerSystem ProgrammingReverse engineering
Sound RecorderВ этом топике вы найдете немного ностальгии, каплю гнева и килограмм реверс-инжиниринга. Посвящается тем, кто знаком с программой «Звукозапись» не понаслышке :)

Когда небо было голубее, Солнце светило ярче, а Интернет был таким недоступным… Короче, в далеком детстве мне почему-то полюбилась стандартная программа «Звукозапись» из Windows 98. Не глядя на минимальную функциональность, я даже умудрялся делать в ней простейшие «ремиксы» ей же записанных мелодий из игр.

Шли годы. Железо становилось мощнее, а ОС функциональнее. Но «Звукозапись» не менялась. Даже в Windows XP она оставалась такой же, как и тогда. Пришло время обновить железо. 3 гигабайта оперативной памяти — раньше и мечтать о таком не приходилось. Этого уж точно должно хватить всем! Так и было, пока дело не дошло до той самой «Звукозаписи». После попытки записать небольшой звук программа невозмутимо возразила, что ей недостаточно оперативной памяти.

Not enough memory available to complete this operation. Quit one or more applications to increase available memory, and then try again.

Что конечно же возмутило меня. Закрыл все программы, попробовал перезагрузиться — не помогло. Страшная мысль о проблеме в программе закралась в голову, и мои опасения оправдались: Microsoft заявляет, что при наличии более 2 гигабайт оперативной памяти программа сообщает о её недостаче, и это особенность архитектуры приложения. Причем не предлагается никакого адекватного способа решения проблемы, кроме уменьшения объема физически доступной памяти. Как говорится, пользуйтесь тем что есть.



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

Очевидно, что в коде проверки количества свободной памяти разработчик объявил переменную:
int AvailableMemory;
Из-за чего число свободных байт рассматривается как знаковое число. При объеме свободной памяти больше двух гигабайт, первый бит устанавливается в единицу, поэтому число выглядит как отрицательное. Для исправления ошибки достаточно было бы написать:
unsigned int AvailableMemory;
Но Microsoft этого не делает, вероятно, для стимуляции перехода на Windows Vista или 7 (шутка), где «Звукозапись», увы, уже совсем другая программа.


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

Отказ от ответственности


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

Инструментарий

  • IDA Pro — для дизассемблирования и исследования приложения
  • Flat Assembler — для генерации необходимых машинных кодов
  • Hexplorer — для внесения изменений в готовый исполняемый файл
  • Resource Hacker — для изучения ресурсов
Более подробно с данными программами можно ознакомиться в предыдущей статье по теме реверс-инжиниринга «Расширение функциональности готовых программ».

Исследование


Для определения количества свободных байт в оперативной памяти используется устаревшая функция GlobalMemoryStatus — именно её мы видим в таблице импорта «Звукозаписи». Поскольку эта функция используется в нескольких местах, более точно определить искомый участок кода нам поможет номер строки в ресурсах, выводимой при ошибке — это строка номер 6Eh.

Забавный факт — функция GlobalMemoryStatus в целях совместимости возвращает не более 2Гб свободной оперативной памяти независимо от того, сколько у вас свободно на самом деле. То есть старший бит числа свободных байт в любом случае не должен быть установлен в единицу, и число не должно интерпретироваться как отрицательное. Для того, чтобы найти проблему, нужно уяснить, что бывают различные типы условных переходов — для знаковых и беззнаковых данных.


Рассмотрим первое условие. Как видно, результат работы функции GlobalMemoryStatus сравнивается со значением, эквивалентным 1Мб. И не глядя на использование знакозависимой команды перехода JGE, данный код в свете ограничения результата GlobalMemoryStatus всегда работает верно. Проблема всплывает при проверке второго условия. Программа вычисляет сумму уже занятой записанным звуком памяти и свободной памяти (что установит старший бит числа), и сравнивает полученное число с количеством необходимых для выделения байт. Естественно, команда перехода для знаковых данных JLE сработает некорректно, и для корректной работы её необходимо заменить командой JBE (для беззнаковых данных). То есть наша задача сводится к замене одной команды.

Патчинг


Физическое смещение интересующей нас команды: 6BD5h. Машинный код JLE — 7Eh. Чтобы получить машинный код команды JBE скомпилируем в Flat Assembler следующий код:
use32
jbe fake
fake:
Получим файл, в котором первым байтом будет код нужной команды — 76h. Осталось дело за малым — внести необходимые изменения в исполняемый файл. Для этого воспользуемся HEX редактором.

Результат


sndrec32.zip (119Кб) — оригинальная и исправленная версии программы из английской Windows XP SP3.

Зачем это было нужно


Just for fun. Не стоит искать здесь никаких рационалистических побуждений. Существует масса других очень достойных и более удобных программ для записи и редактирования аудио. Просто сама возможность запустить и поработать в «той самой программе» греет душу :)
Tags:sndrec32ностальгияasmreverse engineeringмодификация исполняемых файлов
Hubs: Assembler System Programming Reverse engineering
+171
19.4k 88
Comments 98
Popular right now
Reverse-Engineering. Basic
December 23, 202050,000 ₽OTUS
Профессия iOS-разработчик
November 30, 202075,000 ₽SkillFactory
Основы HTML и CSS
November 30, 2020FreeНетология
Frontend-разработчик с нуля
November 30, 202077,940 ₽Нетология
SMM-менеджер
November 30, 202059,998 ₽GeekBrains
Top of the last 24 hours